home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Programming / fpc / compiler / ratti386.pas < prev    next >
Pascal/Delphi Source File  |  1998-09-24  |  152KB  |  3,808 lines

  1. {
  2.     $Id: ratti386.pas,v 1.2.2.1 1998/05/25 22:57:32 carl Exp $
  3.     Copyright (c) 1997-98 by Carl Eric Codere
  4.  
  5.     Does the parsing for the AT&T styled inline assembler.
  6.  
  7.     This program is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU General Public License as published by
  9.     the Free Software Foundation; either version 2 of the License, or
  10.     (at your option) any later version.
  11.  
  12.     This program is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.  
  17.     You should have received a copy of the GNU General Public License
  18.     along with this program; if not, write to the Free Software
  19.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21.  ****************************************************************************
  22. }
  23. Unit Ratti386;
  24. {**********************************************************************}
  25. { WARNING                                                              }
  26. {**********************************************************************}
  27. {  Any modification in the order or removal of terms in the tables     }
  28. {  in i386.pas and intasmi3.pas will BREAK the code in this unit,      }
  29. {  unless the appropriate changes are made to this unit. Addition      }
  30. {  of terms though, will not change the code herein.                   }
  31. {**********************************************************************}
  32.  
  33. {--------------------------------------------------------------------}
  34. { LEFT TO DO:                                                        }
  35. {--------------------------------------------------------------------}
  36. { o Handle record offsets                                            }
  37. { o Add support imul,shld and shrd.                                  }
  38. { o Add support for nor operators.                                   }
  39. { o Bugfix of ao_imm8s for IMUL. (Currently the 3 operand imul will  }
  40. {   be considered as invalid because I use ao_imm8 and the table     }
  41. {   uses ao_imm8s).                                                  }
  42. { o In ConcatOpCode add more checking regarding suffixes and         }
  43. {   destination registers. (started but unfinished).                 }
  44. {--------------------------------------------------------------------}
  45. Interface
  46.  
  47. uses
  48.   i386,tree;
  49.  
  50.    function assemble: ptree;
  51.  
  52. const
  53.  { this variable is TRUE if the lookup tables have already been setup  }
  54.  { for fast access. On the first call to assemble the tables are setup }
  55.  { and stay set up.                                                    }
  56.  _asmsorted: boolean = FALSE;
  57.  firstreg       = R_EAX;
  58.  lastreg        = R_ST7;
  59.  { Hack to support all opcodes in the i386 table    }
  60.  { only tokens up to and including lastop_in_table  }
  61.  { are checked for validity, otherwise...           }
  62.  lastop_in_table = A_POPFD;
  63.  
  64. type
  65.  tiasmops = array[firstop..lastop] of string[7];
  66.  piasmops = ^tiasmops;
  67.  
  68. var
  69.  { sorted tables of opcodes }
  70.  iasmops: piasmops;
  71.  { uppercased tables of registers }
  72.  iasmregs: array[firstreg..lastreg] of string[6];
  73.  
  74.  
  75. Implementation
  76.  
  77. Uses
  78.   aasm,globals,AsmUtils,strings,hcodegen,scanner,
  79.   cobjects,verbose,symtable;
  80.  
  81. type
  82.  tinteltoken = (
  83.    AS_NONE,AS_LABEL,AS_LLABEL,AS_STRING,AS_HEXNUM,AS_OCTALNUM,
  84.    AS_BINNUM,AS_REALNUM,AS_COMMA,AS_LPAREN,
  85.    AS_RPAREN,AS_COLON,AS_DOT,AS_PLUS,AS_MINUS,AS_STAR,AS_INTNUM,
  86.    AS_SEPARATOR,AS_ID,AS_REGISTER,AS_OPCODE,AS_SLASH,AS_DOLLAR,
  87.      {------------------ Assembler directives --------------------}
  88.    AS_DB,AS_DW,AS_DD,AS_DQ,AS_GLOBAL,AS_ALIGN,AS_ASCII,
  89.    AS_ASCIIZ,AS_LCOMM,AS_COMM,AS_SINGLE,AS_DOUBLE,AS_EXTENDED,
  90.    AS_DATA,AS_TEXT,AS_END,
  91.      {------------------ Assembler Operators  --------------------}
  92.    AS_MOD,AS_SHL,AS_SHR,AS_NOT,AS_AND,AS_OR,AS_XOR,AS_NOR);
  93.  
  94.    tasmkeyword = string[8];
  95. const
  96.    { These tokens should be modified accordingly to the modifications }
  97.    { in the different enumerations.                                   }
  98.    firstdirective = AS_DB;
  99.    lastdirective  = AS_END;
  100.    firstsreg      = R_CS;
  101.    lastsreg       = R_SS;
  102.  
  103.        _count_asmdirectives = longint(lastdirective)-longint(firstdirective);
  104.        _count_asmprefixes   = 5;
  105.        _count_asmspecialops = 25;
  106.        _count_asmoverrides  = 3;
  107.  
  108.        _asmdirectives : array[0.._count_asmdirectives] of tasmkeyword =
  109.        ('.byte','.word','.long','.quad','.globl','.align','.ascii',
  110.         '.asciz','.lcomm','.comm','.single','.double','.tfloat',
  111.         '.data','.text','END');
  112.  
  113.      {------------------ Missing opcodes from std list  ----------------}
  114.        _asmprefixes: array[0.._count_asmprefixes] of tasmkeyword = (
  115.        'REPNE','REPE','REP','REPZ','REPNZ','LOCK');
  116.  
  117.        _prefixtokens: array[0.._count_asmprefixes] of tasmop = (
  118.        A_REPNE,A_REPE,A_REP,A_REPE,A_REPNE,A_LOCK);
  119.  
  120.        _specialops: array[0.._count_asmspecialops] of tasmkeyword = (
  121.        'CMPSB','CMPSW','CMPSL','INSB','INSW','INSL','OUTSB','OUTSW','OUTSL',
  122.        'SCASB','SCASW','SCASL','STOSB','STOSW','STOSL','MOVSB','MOVSW','MOVSL',
  123.        'LODSB','LODSW','LODSL','LOCK','SEGCS','SEGDS','SEGES','SEGSS');
  124.  
  125.        _specialopstokens: array[0.._count_asmspecialops] of tasmop = (
  126.        A_CMPS,A_CMPS,A_CMPS,A_INS,A_INS,A_INS,A_OUTS,A_OUTS,A_OUTS,
  127.        A_SCAS,A_SCAS,A_SCAS,A_STOS,A_STOS,A_STOS,A_MOVS,A_MOVS,A_MOVS,
  128.        A_LODS,A_LODS,A_LODS,A_LOCK,A_NONE,A_NONE,A_NONE,A_NONE);
  129.      {------------------------------------------------------------------}
  130.        { register type definition table for easier searching }
  131.        _regtypes:array[firstreg..lastreg] of longint =
  132.        (ao_reg32,ao_reg32,ao_reg32,ao_reg32,ao_reg32,ao_reg32,ao_reg32,ao_reg32,
  133.        ao_reg16,ao_reg16,ao_reg16,ao_reg16,ao_reg16,ao_reg16,ao_reg16,ao_reg16,
  134.        ao_reg8,ao_reg8,ao_reg8,ao_reg8,ao_reg8,ao_reg8,ao_reg8,ao_reg8,
  135.        ao_none,ao_sreg2,ao_sreg2,ao_sreg2,ao_sreg3,ao_sreg3,ao_sreg2,
  136.        ao_floatacc,ao_floatacc,ao_floatreg,ao_floatreg,ao_floatreg,ao_floatreg,
  137.        ao_floatreg,ao_floatreg,ao_floatreg);
  138.  
  139.        _regsizes: array[firstreg..lastreg] of topsize =
  140.        (S_L,S_L,S_L,S_L,S_L,S_L,S_L,S_L,
  141.         S_W,S_W,S_W,S_W,S_W,S_W,S_W,S_W,
  142.         S_B,S_B,S_B,S_B,S_B,S_B,S_B,S_B,
  143.         { segment register }
  144.         S_W,S_W,S_W,S_W,S_W,S_W,S_W,
  145.         { can also be S_S or S_T - must be checked at run-time }
  146.         S_Q,S_Q,S_Q,S_Q,S_Q,S_Q,S_Q,S_Q,S_Q);
  147.  
  148.        _constsizes: array[S_NO..S_S] of longint =
  149.        (0,ao_imm8,ao_imm16,ao_imm32,0,0,0,0,ao_imm32);
  150.  
  151.  
  152.        { converts from AT&T style to non-specific style... }
  153.       {'fildq','filds',
  154.      'fildl','fldl','fldt','fistq','fists','fistl','fstl','fsts',
  155.       'fstps','fistpl','fstpl','fistps','fistpq','fstpt','fcomps',
  156.       'ficompl','fcompl','ficomps','fcoms','ficoml','fcoml','ficoms',
  157.       'fiaddl','faddl','fiadds','fisubl','fsubl','fisubs','fsubs',
  158.       'fsubr','fsubrs','fisubrl','fsubrl','fisubrs','fmuls','fimull',
  159.       'fmull','fimuls','fdivs','fidivl','fdivl','fidivs','fdivrs',
  160.       'fidivrl','fdivrl','fidivrs','repe','repne','fadds','popfl', }
  161.        _fpusizes:array[A_FILDQ..A_FIDIVRS] of topsize = (
  162.                  S_Q,S_S,S_L,S_L,S_X,S_Q,S_S,S_L,S_L,S_S,
  163.                  S_S,S_L,S_L,S_S,S_Q,S_X,
  164.                  S_S,S_L,S_L,S_S,
  165.                  S_S,S_L,S_L,S_S,S_L,S_L,S_S,
  166.                  S_L,S_L,S_S,S_S,S_NO,S_S,S_L,
  167.                  S_L,S_S,S_S,S_L,S_L,S_S,S_S,S_L,
  168.                  S_L,S_S,S_S,S_L,S_L,S_S);
  169.        _fpuopcodes:array[A_FILDQ..A_FIDIVRS] of tasmop = (
  170.        A_FILD,A_FILD,A_FILD,A_FLD,A_FLD,A_FIST,A_FIST,A_FIST,A_FST,A_FST,
  171.        A_FSTP,A_FISTP,A_FSTP,A_FISTP,A_FISTP,A_FSTP,
  172.        A_FCOMP,A_FICOMP,A_FCOMP,A_FICOMP,
  173.        A_FCOM,A_FICOM,A_FCOM,A_FICOM,A_FIADD,A_FADD,A_FIADD,
  174.        A_FISUB,A_FSUB,A_FISUB,A_FSUB,A_FSUB,A_FSUBR,A_FISUBR,
  175.        A_FSUBR,A_FISUBR,A_FMUL,A_FIMUL,A_FMUL,A_FIMUL,A_FDIV,A_FIDIV,
  176.        A_FDIV,A_FIDIV,A_FDIVR,A_FIDIVR,A_FDIVR,A_FIDIVR);
  177.  
  178.  const
  179.   newline = #10;
  180.   firsttoken : boolean = TRUE;
  181.   operandnum : byte = 0;
  182.  charcount: byte = 0;
  183.  var
  184.  p : paasmoutput;
  185.  actasmtoken: tinteltoken;
  186.  actasmpattern: string;
  187.  c: char;
  188.  Instr: TInstruction;
  189.  labellist: TAsmLabelList;
  190.  line: string; { CHanged from const to var, there is a bug in 0.9.1 which
  191.                  doesn't allow 255-char constant strings. MVC}
  192.  
  193.    Procedure SetupTables;
  194.    { creates uppercased symbol tables. }
  195.    var
  196.      i: tasmop;
  197.      j: tregister;
  198.    Begin
  199.      Message(assem_d_creating_lookup_tables);
  200.      { opcodes }
  201.      new(iasmops);
  202.      for i:=firstop to lastop do
  203.       iasmops^[i] := upper(att_op2str[i]);
  204.      { opcodes }
  205.      for j:=firstreg to lastreg do
  206.       iasmregs[j] := upper(att_reg2str[j]);
  207.    end;
  208.  
  209.   {---------------------------------------------------------------------}
  210.   {                     Routines for the tokenizing                     }
  211.   {---------------------------------------------------------------------}
  212.  
  213.    function is_asmopcode(const s: string):Boolean;
  214.   {*********************************************************************}
  215.   { FUNCTION is_asmopcode(s: string):Boolean                            }
  216.   {  Description: Determines if the s string is a valid opcode          }
  217.   {  if so returns TRUE otherwise returns FALSE.                        }
  218.   {*********************************************************************}
  219.    var
  220.     i: tasmop;
  221.     j: byte;
  222.     hs: topsize;
  223.     hid: string;
  224.    Begin
  225.      is_asmopcode := FALSE;
  226.      { first search for extended opcodes }
  227.      for j:=0 to _count_asmspecialops do
  228.      Begin
  229.        if s = _specialops[j] then
  230.        Begin
  231.          is_asmopcode:=TRUE;
  232.          exit;
  233.        end;
  234.      end;
  235.  
  236.      for i:=firstop to lastop do
  237.      Begin
  238.             if s=iasmops^[i] then
  239.              begin
  240.                is_asmopcode := TRUE;
  241.                exit
  242.              end;
  243.      end;
  244.      { not found yet ... }
  245.      { search for all possible suffixes }
  246.      for hs:=S_WL downto S_B do
  247.         if copy(s,length(s)-length(att_opsize2str[hs])+1,
  248.           length(att_opsize2str[hs]))=upper(att_opsize2str[hs]) then
  249.         begin
  250.            { here we search the entire table... }
  251.            hid:=copy(s,1,length(s)-length(att_opsize2str[hs]));
  252.            for i:=firstop to lastop do
  253.               if (length(hid) > 0) and (hid=iasmops^[i]) then
  254.               begin
  255.                 is_asmopcode := TRUE;
  256.                 exit;
  257.               end;
  258.         end;
  259.    end;
  260.  
  261.  
  262.  
  263.    Procedure is_asmdirective(const s: string; var token: tinteltoken);
  264.   {*********************************************************************}
  265.   { FUNCTION is_asmdirective(s: string; var token: tinteltoken):Boolean }
  266.   {  Description: Determines if the s string is a valid directive       }
  267.   { (an operator can occur in operand fields, while a directive cannot) }
  268.   {  if so returns the directive token, otherwise does not change token.}
  269.   {*********************************************************************}
  270.    var
  271.     i:byte;
  272.    Begin
  273.      for i:=0 to _count_asmdirectives do
  274.      begin
  275.         if s=_asmdirectives[i] then
  276.         begin
  277.            token := tinteltoken(longint(firstdirective)+i);
  278.            exit;
  279.         end;
  280.      end;
  281.    end;
  282.  
  283.  
  284.    Procedure is_register(const s: string; var token: tinteltoken);
  285.   {*********************************************************************}
  286.   { PROCEDURE is_register(s: string; var token: tinteltoken);           }
  287.   {  Description: Determines if the s string is a valid register, if    }
  288.   {  so return token equal to A_REGISTER, otherwise does not change token}
  289.   {*********************************************************************}
  290.    Var
  291.     i: tregister;
  292.    Begin
  293.      for i:=firstreg to lastreg do
  294.      begin
  295.       if s=iasmregs[i] then
  296.       begin
  297.         token := AS_REGISTER;
  298.         exit;
  299.       end;
  300.      end;
  301.    end;
  302.  
  303.  
  304.   Function GetToken: tinteltoken;
  305.   {*********************************************************************}
  306.   { FUNCTION GetToken: tinteltoken;                                     }
  307.   {  Description: This routine returns intel assembler tokens and       }
  308.   {  does some minor syntax error checking.                             }
  309.   {*********************************************************************}
  310.   var
  311.    token: tinteltoken;
  312.    forcelabel: boolean;
  313.    errorflag : boolean;
  314.    temp: string;
  315.    code: integer;
  316.    value: byte;
  317.   begin
  318.     errorflag := FALSE;
  319.     forcelabel := FALSE;
  320.     actasmpattern :='';
  321.     {* INIT TOKEN TO NOTHING *}
  322.     token := AS_NONE;
  323.     { while space and tab , continue scan... }
  324.     while (c = ' ') or (c = #9) do
  325.     begin
  326.       c := asmgetchar;
  327.     end;
  328.     { Possiblities for first token in a statement:                }
  329.     {   Local Label, Label, Directive, Prefix or Opcode....       }
  330.     if firsttoken and not (c in [newline,#13,'{',';']) then
  331.     begin
  332.       firsttoken := FALSE;
  333.       { directive or local labe }
  334.       if c = '.' then
  335.       begin
  336.         actasmpattern := c;
  337.         { Let us point to the next character }
  338.         c := asmgetchar;
  339.         while c in ['A'..'Z','a'..'z','0'..'9','_','$'] do
  340.         begin
  341.          actasmpattern := actasmpattern + c;
  342.          c := asmgetchar;
  343.         end;
  344.  
  345.         { this is a local label... }
  346.         if (actasmpattern[2] = 'L') and (c = ':') then
  347.         Begin
  348.           { local variables are case sensitive }
  349.           gettoken := AS_LLABEL;
  350.           { delete .L }
  351.           delete(actasmpattern,1,1);
  352.           delete(actasmpattern,1,1);
  353.           { point to next character ... }
  354.           c := asmgetchar;
  355.           exit;
  356.         end
  357.         { must be a directive }
  358.         else
  359.         Begin
  360.          { directives are case sensitive!! }
  361.          is_asmdirective(actasmpattern, token);
  362.          if (token <> AS_NONE) then
  363.           Begin
  364.             gettoken := token;
  365.             exit;
  366.           end
  367.          else
  368.            Message1(assem_e_not_directive_or_local_symbol,actasmpattern);
  369.         end;
  370.       end; { endif }
  371.  
  372.  
  373.       if c='/' then
  374.         begin
  375.            c:=asmgetchar;
  376.            { att styled comment }
  377.            if c='/' then
  378.              begin
  379.                 repeat
  380.                    c:=asmgetchar;
  381.                 until c=newline;
  382.                 firsttoken := TRUE;
  383.                 gettoken:=AS_SEPARATOR;
  384.                 c:=asmgetchar;
  385.                 exit;
  386.              end
  387.            else
  388.              Message(assem_e_slash_at_begin_of_line_not_allowed);
  389.         end;
  390.       { only opcodes and global labels are allowed now. }
  391.       while c in ['A'..'Z','a'..'z','0'..'9','_'] do
  392.       begin
  393.          actasmpattern := actasmpattern + c;
  394.          c := asmgetchar;
  395.       end;
  396.  
  397.       if c = ':' then
  398.       begin
  399.            uppervar(actasmpattern);
  400.            token := AS_LABEL;
  401.            { let us point to the next character }
  402.            c := asmgetchar;
  403.            gettoken := token;
  404.            exit;
  405.       end;
  406.  
  407.  
  408.       If is_asmopcode(upper(actasmpattern)) then
  409.       Begin
  410.        uppervar(actasmpattern);
  411.        gettoken := AS_OPCODE;
  412.        exit;
  413.       end
  414.       else
  415.       if upper(actasmpattern) = 'END' then
  416.       begin
  417.          gettoken := AS_END;
  418.          exit;
  419.       end
  420.       else
  421.       begin
  422.          gettoken := AS_NONE;
  423.          Message(assem_e_invalid_operand);
  424.       end;
  425.     end
  426.     else { else firsttoken }
  427.     { Here we must handle all possible cases                              }
  428.     begin
  429.       case c of
  430.  
  431.          '.':   { possiblities : - local label reference , such as in jmp @local1 }
  432.                 {                - directive.                                     }
  433.                             begin
  434.                              actasmpattern := c;
  435.                              c:= asmgetchar;
  436.                              while c in  ['A'..'Z','a'..'z','0'..'9','_','$'] do
  437.                              begin
  438.                                actasmpattern := actasmpattern + c;
  439.                                c := asmgetchar;
  440.                              end;
  441.                              is_asmdirective(actasmpattern,token);
  442.                              { if directive }
  443.                              if (token <> AS_NONE) then
  444.                              begin
  445.                                gettoken := token;
  446.                                exit;
  447.                              end;
  448.                              { local label references and directives }
  449.                              { are case sensitive                    }
  450.                              gettoken := AS_ID;
  451.                              exit;
  452.                             end;
  453.       { identifier, register, opcode, prefix or directive }
  454.          '_','A'..'Z','a'..'z': begin
  455.                              actasmpattern := c;
  456.                              c:= asmgetchar;
  457.                              while c in  ['A'..'Z','a'..'z','0'..'9','_','$'] do
  458.                              begin
  459.                                actasmpattern := actasmpattern + c;
  460.                                c := asmgetchar;
  461.                              end;
  462.                              { pascal is not case sensitive!    }
  463.                              { therefore variables which are    }
  464.                              { outside the scope of the asm     }
  465.                              { block, should not be made case   }
  466.                              { sensitive...  !!!!!              }
  467.                              uppervar(actasmpattern);
  468.  
  469.                              If is_asmopcode(actasmpattern) then
  470.                              Begin
  471.                                     gettoken := AS_OPCODE;
  472.                                     exit;
  473.                              end;
  474.                              { we handle this directive separately from }
  475.                              { others.                                  }
  476.                              if actasmpattern = 'END' then
  477.                              Begin
  478.                                  gettoken := AS_END;
  479.                                  exit;
  480.                              end;
  481.  
  482.                              { if found }
  483.                              if (token <> AS_NONE) then
  484.                              begin
  485.                                gettoken := token;
  486.                                exit;
  487.                              end
  488.                              { this is surely an identifier }
  489.                              else
  490.                                token := AS_ID;
  491.                              gettoken := token;
  492.                              exit;
  493.                           end;
  494.            '&':       begin
  495.                          c:=asmgetchar;
  496.                          gettoken := AS_AND;
  497.                       end;
  498.            { character }
  499.            '''' :     begin
  500.                          c:=asmgetchar;
  501.                          if c = '\' then
  502.                          Begin
  503.                            { escape sequence }
  504.                            c:=asmgetchar;
  505.                            case c of
  506.                          newline: Message(scan_f_string_exceeds_line);
  507.                              't': actasmpattern:=#09;
  508.                              'b': actasmpattern:=#08;
  509.                              '\': actasmpattern:='\';
  510.                              'f': actasmpattern:=#12;
  511.                              'n': actasmpattern:=#10;
  512.                              'r': actasmpattern:=#13;
  513.                              '"': actasmpattern:='"';
  514.                              { octal number }
  515.                              '0'..'7':
  516.                                 begin
  517.                                    temp:=c;
  518.                                    temp:=temp+asmgetchar;
  519.                                    temp:=temp+asmgetchar;
  520.                                    val(octaltodec(temp),value,code);
  521.                                    if (code <> 0) then
  522.                                     Message1(assem_e_error_in_octal_const,temp);
  523.                                    actasmpattern:=chr(value);
  524.                                 end;
  525.                              { hexadecimal number }
  526.                              'x':
  527.                                  begin
  528.                                    temp:=asmgetchar;
  529.                                    temp:=temp+asmgetchar;
  530.                                    val(hextodec(temp),value,code);
  531.                                    if (code <> 0) then
  532.                                     Message1(assem_e_error_in_hex_const,temp);
  533.                                    actasmpattern:=chr(value);
  534.                                  end;
  535.                              else
  536.                               Begin
  537.                                 Message(assem_e_escape_seq_ignored);
  538.                                 actasmpattern:=c;
  539.                               end
  540.                            end; { end case }
  541.                          end
  542.                          else
  543.                            actasmpattern:=c;
  544.  
  545.                          gettoken := AS_STRING;
  546.                          c:=asmgetchar;
  547.                          exit;
  548.  
  549.                       end;
  550.            { string }
  551.            '"' :
  552.                       begin
  553.                          actasmpattern:='';
  554.                          while true do
  555.                          Begin
  556.                            c:=asmgetchar;
  557.                            case c of
  558.                             '\': Begin
  559.                                   { escape sequences }
  560.                                   c:=asmgetchar;
  561.                                   case c of
  562.                                    newline: Message(scan_f_string_exceeds_line);
  563.                                    't': actasmpattern:=actasmpattern+#09;
  564.                                    'b': actasmpattern:=actasmpattern+#08;
  565.                                    '\': actasmpattern:=actasmpattern+'\';
  566.                                    'f': actasmpattern:=actasmpattern+#12;
  567.                                    'n': actasmpattern:=actasmpattern+#10;
  568.                                    'r': actasmpattern:=actasmpattern+#13;
  569.                                    '"': actasmpattern:=actasmpattern+'"';
  570.                                    { octal number }
  571.                                    '0'..'7':
  572.                                       begin
  573.                                            temp:=c;
  574.                                            temp:=temp+asmgetchar;
  575.                                            temp:=temp+asmgetchar;
  576.                                            val(octaltodec(temp),value,code);
  577.                                            if (code <> 0) then
  578.                                             Message1(assem_e_error_in_octal_const,temp);
  579.                                            actasmpattern:=actasmpattern+chr(value);
  580.                                       end;
  581.                                    { hexadecimal number }
  582.                                    'x':
  583.                                      begin
  584.                                        temp:=asmgetchar;
  585.                                        temp:=temp+asmgetchar;
  586.                                        val(hextodec(temp),value,code);
  587.                                        if (code <> 0) then
  588.                                         Message1(assem_e_error_in_hex_const,temp);
  589.                                        actasmpattern:=actasmpattern+chr(value);
  590.                                      end;
  591.                                    else
  592.                                      Begin
  593.                                        Message(assem_e_escape_seq_ignored);
  594.                                        actasmpattern:=actasmpattern+c;
  595.                                      end
  596.                                    end; { end case }
  597.                                  end;
  598.                             '"': begin
  599.                                   c:=asmgetchar;
  600.                                   break;
  601.                                  end;
  602.                             newline: Message(scan_f_string_exceeds_line);
  603.                            else
  604.                              actasmpattern:=actasmpattern+c;
  605.                            end;
  606.                          end; { end case }
  607.                    token := AS_STRING;
  608.                    gettoken := token;
  609.                    exit;
  610.                  end;
  611.            '$' :  begin
  612.                    gettoken := AS_DOLLAR;
  613.                    c:=asmgetchar;
  614.                    exit;
  615.                   end;
  616.            ',' : begin
  617.                    gettoken := AS_COMMA;
  618.                    c:=asmgetchar;
  619.                    exit;
  620.                  end;
  621.            '<' : begin
  622.                    gettoken := AS_SHL;
  623.                    c := asmgetchar;
  624.                    if c = '<' then
  625.                      c := asmgetchar;
  626.                    exit;
  627.                  end;
  628.            '>' : begin
  629.                    gettoken := AS_SHL;
  630.                    c := asmgetchar;
  631.                    if c = '>' then
  632.                      c := asmgetchar;
  633.                    exit;
  634.                  end;
  635.            '|' : begin
  636.                    gettoken := AS_OR;
  637.                    c := asmgetchar;
  638.                    exit;
  639.                  end;
  640.            '^' : begin
  641.                   gettoken := AS_XOR;
  642.                   c := asmgetchar;
  643.                   exit;
  644.                  end;
  645.            '!' : begin
  646.                   Message(assem_e_nor_not_supported);
  647.                   c := asmgetchar;
  648.                   gettoken := AS_NONE;
  649.                   exit;
  650.                  end;
  651.            '(' : begin
  652.                    gettoken := AS_LPAREN;
  653.                    c:=asmgetchar;
  654.                    exit;
  655.                  end;
  656.            ')' : begin
  657.                    gettoken := AS_RPAREN;
  658.                    c:=asmgetchar;
  659.                    exit;
  660.                  end;
  661.            ':' : begin
  662.                    gettoken := AS_COLON;
  663.                    c:=asmgetchar;
  664.                    exit;
  665.                  end;
  666.            '+' : begin
  667.                    gettoken := AS_PLUS;
  668.                    c:=asmgetchar;
  669.                    exit;
  670.                  end;
  671.            '-' : begin
  672.                    gettoken := AS_MINUS;
  673.                    c:=asmgetchar;
  674.                    exit;
  675.                  end;
  676.            '*' : begin
  677.                    gettoken := AS_STAR;
  678.                    c:=asmgetchar;
  679.                    exit;
  680.                  end;
  681.            '/' : begin
  682.                    c:=asmgetchar;
  683.                    { att styled comment }
  684.                    if c='/' then
  685.                      begin
  686.                         repeat
  687.                            c:=asmgetchar;
  688.                         until c=newline;
  689.                         firsttoken := TRUE;
  690.                         gettoken:=AS_SEPARATOR;
  691.                         c:=asmgetchar;
  692.                         exit;
  693.                      end
  694.                    else
  695.                      begin
  696.                         gettoken := AS_SLASH;
  697.                         c:=asmgetchar;
  698.                         exit;
  699.                      end;
  700.                  end;
  701.            { register or modulo      }
  702.            { only register supported }
  703.            { for the moment.         }
  704.            '%' : begin
  705.                      actasmpattern := c;
  706.                      c:=asmgetchar;
  707.                      while c in ['a'..'z','A'..'Z','0'..'9'] do
  708.                      Begin
  709.                         actasmpattern := actasmpattern + c;
  710.                         c:=asmgetchar;
  711.                      end;
  712.                      token := AS_NONE;
  713.                      uppervar(actasmpattern);
  714.                      if (actasmpattern = '%ST') and (c='(') then
  715.                      Begin
  716.                         actasmpattern:=actasmpattern+c;
  717.                         c:=asmgetchar;
  718.                         if c in ['0'..'9'] then
  719.                           actasmpattern := actasmpattern + c
  720.                         else
  721.                           Message(assem_e_invalid_fpu_register);
  722.                         c:=asmgetchar;
  723.                         if c <> ')' then
  724.                           Message(assem_e_invalid_fpu_register)
  725.                         else
  726.                         Begin
  727.                           actasmpattern := actasmpattern + c;
  728.                           c:=asmgetchar; { let us point to next character. }
  729.                         end;
  730.                      end;
  731.                      is_register(actasmpattern, token);
  732.                      { if found }
  733.                      if (token <> AS_NONE) then
  734.                      begin
  735.                         gettoken := token;
  736.                         exit;
  737.                      end
  738.                      else
  739.                        Message(assem_w_modulo_not_supported);
  740.                  end;
  741.            { integer number }
  742.            '1'..'9': begin
  743.                         actasmpattern := c;
  744.                         c := asmgetchar;
  745.                         while c in ['0'..'9'] do
  746.                           Begin
  747.                              actasmpattern := actasmpattern + c;
  748.                              c:= asmgetchar;
  749.                           end;
  750.                         gettoken := AS_INTNUM;
  751.                         exit;
  752.                      end;
  753.            '0': begin
  754.                 { octal,hexa,real or binary number. }
  755.                  actasmpattern := c;
  756.                  c:=asmgetchar;
  757.                  case upcase(c) of
  758.                    { binary }
  759.                    'B': Begin
  760.                           c:=asmgetchar;
  761.                           while c in ['0','1'] do
  762.                           Begin
  763.                             actasmpattern := actasmpattern + c;
  764.                             c := asmgetchar;
  765.                           end;
  766.                           gettoken := AS_BINNUM;
  767.                           exit;
  768.                         end;
  769.                    { real }
  770.                    'D': Begin
  771.                           c:=asmgetchar;
  772.                           { get ridd of the 0d }
  773.                           if (c='+') or (c='-') then
  774.                             begin
  775.                                actasmpattern:=c;
  776.                                c:=asmgetchar;
  777.                             end
  778.                           else
  779.                             actasmpattern:='';
  780.                         while c in ['0'..'9'] do
  781.                           Begin
  782.                              actasmpattern := actasmpattern + c;
  783.                              c:= asmgetchar;
  784.                           end;
  785.                         if c='.' then
  786.                           begin
  787.                              actasmpattern := actasmpattern + c;
  788.                              c:=asmgetchar;
  789.                              while c in ['0'..'9'] do
  790.                                Begin
  791.                                   actasmpattern := actasmpattern + c;
  792.                                   c:= asmgetchar;
  793.                                end;
  794.                              if upcase(c) = 'E' then
  795.                                begin
  796.                                   actasmpattern := actasmpattern + c;
  797.                                   c:=asmgetchar;
  798.                                   if (c = '+') or (c = '-') then
  799.                                     begin
  800.                                        actasmpattern := actasmpattern + c;
  801.                                        c:=asmgetchar;
  802.                                     end;
  803.                                   while c in ['0'..'9'] do
  804.                                     Begin
  805.                                        actasmpattern := actasmpattern + c;
  806.                                        c:= asmgetchar;
  807.                                     end;
  808.                                end;
  809.                              gettoken := AS_REALNUM;
  810.                              exit;
  811.                           end
  812.                         else
  813.                             Message1(assem_e_invalid_float_const,actasmpattern+c);
  814.                         end;
  815.                    { hexadecimal }
  816.                    'X': Begin
  817.                           c:=asmgetchar;
  818.                           while c in ['0'..'9','a'..'f','A'..'F'] do
  819.                           Begin
  820.                             actasmpattern := actasmpattern + c;
  821.                             c := asmgetchar;
  822.                           end;
  823.                           gettoken := AS_HEXNUM;
  824.                           exit;
  825.                         end;
  826.                    { octal }
  827.                    '1'..'7': begin
  828.                                actasmpattern := actasmpattern + c;
  829.                                while c in ['0'..'7'] do
  830.                                Begin
  831.                                  actasmpattern := actasmpattern + c;
  832.                                  c := asmgetchar;
  833.                                end;
  834.                                gettoken := AS_OCTALNUM;
  835.                                exit;
  836.                              end;
  837.                     else { octal number zero value...}
  838.                       Begin
  839.                          gettoken := AS_OCTALNUM;
  840.                          exit;
  841.                       end;
  842.                    end; { end case }
  843.                 end;
  844.  
  845.          '{',#13,newline,';' : begin
  846.                             { the comment is read by asmgetchar }
  847.                             c:=asmgetchar;
  848.                             firsttoken := TRUE;
  849.                             gettoken:=AS_SEPARATOR;
  850.                            end;
  851.             else
  852.              Begin
  853.                Message(scan_f_illegal_char);
  854.              end;
  855.  
  856.       end; { end case }
  857.     end; { end else if }
  858.   end;
  859.  
  860.  
  861.   {---------------------------------------------------------------------}
  862.   {                     Routines for the output                         }
  863.   {---------------------------------------------------------------------}
  864.  
  865.  
  866.   { looks for internal names of variables and routines }
  867.   Function SearchDirectVar(var Instr: TInstruction; const hs:string;operandnum:byte): Boolean;
  868.   var
  869.     p : pai_external;
  870.   Begin
  871.      SearchDirectVar:=false;
  872.      { search in the list of internals }
  873.      p:=search_assembler_symbol(internals,hs,EXT_ANY);
  874.        if p=nil then
  875.          p:=search_assembler_symbol(externals,hs,EXT_ANY);
  876.      if p<>nil then
  877.        begin
  878.          { get symbol name                                  }
  879.          { free the memory before changing the symbol name. }
  880.          if assigned(instr.operands[operandnum].ref.symbol) then
  881.            FreeMem(instr.operands[operandnum].ref.symbol,
  882.                length(instr.operands[operandnum].ref.symbol^)+1);
  883.          instr.operands[operandnum].ref.symbol:=newpasstr(strpas(p^.name));
  884.            case p^.exttyp of
  885.              EXT_BYTE   : instr.operands[operandnum].size := S_B;
  886.              EXT_WORD   : instr.operands[operandnum].size := S_W;
  887.              EXT_NEAR,EXT_FAR,EXT_PROC,EXT_DWORD,EXT_CODEPTR,EXT_DATAPTR:
  888.              instr.operands[operandnum].size := S_L;
  889.              EXT_QWORD  : instr.operands[operandnum].size := S_Q;
  890.              EXT_TBYTE  : instr.operands[operandnum].size := S_X;
  891.            else
  892.              { this is in the case where the instruction is LEA }
  893.              { or something like that, in that case size is not }
  894.              { important.                                       }
  895.                instr.operands[operandnum].size := S_NO;
  896.            end;
  897.          SearchDirectVar := TRUE;
  898.          Exit;
  899.        end;
  900.   end;
  901.  
  902.  
  903.    { returns an appropriate ao_xxxx flag indicating the type }
  904.    { of operand.                                             }
  905.    function findtype(Var Opr: TOperand): longint;
  906.    Begin
  907.     With Opr do
  908.     Begin
  909.      case operandtype of
  910.        OPR_REFERENCE:   Begin
  911.                            if assigned(ref.symbol) then
  912.                            { check if in local label list }
  913.                            { if so then it is considered  }
  914.                            { as a displacement.           }
  915.                            Begin
  916.                              if labellist.search(ref.symbol^) <> nil then
  917.                                findtype := ao_disp
  918.                              else
  919.                                findtype := ao_mem; { probably a mem ref. }
  920.                            end
  921.                            else
  922.                             findtype := ao_mem;
  923.                         end;
  924.        OPR_CONSTANT: Begin
  925.                        { check if there is not already a default size }
  926.                        if opr.size <> S_NO then
  927.                        Begin
  928.                           findtype := _constsizes[opr.size];
  929.                          exit;
  930.                        end;
  931.                        if val < $ff then
  932.                        Begin
  933.                          findtype := ao_imm8;
  934.                          opr.size := S_B;
  935.                        end
  936.                        else if val < $ffff then
  937.                        Begin
  938.                          findtype := ao_imm16;
  939.                          opr.size := S_W;
  940.                        end
  941.                        else
  942.                        Begin
  943.                          findtype := ao_imm32;
  944.                          opr.size := S_L;
  945.                        end
  946.                      end;
  947.        OPR_REGISTER: Begin
  948.                       findtype := _regtypes[reg];
  949.                       exit;
  950.                      end;
  951.        OPR_NONE:     Begin
  952.                        findtype := 0;
  953.                      end;
  954.        else
  955.        Begin
  956.         Message(assem_f_internal_error_in_findtype);
  957.        end;
  958.      end;
  959.     end;
  960.    end;
  961.  
  962.  
  963.    Procedure HandleExtend(var instr: TInstruction);
  964.    { Handles MOVZX, MOVSX ... }
  965.    var
  966.      instruc: tasmop;
  967.      opsize: topsize;
  968.    Begin
  969.       instruc:=instr.getinstruction;
  970.       { if we have A_MOVZX/A_MOVSX here, there is a big problem }
  971.       { it should never happen, because it is already replaced  }
  972.       { by ConcatOpcode!                                        }
  973.       if (instruc in [A_MOVZX,A_MOVSX]) then
  974.        Message(assem_f_internal_error_in_handleextend)
  975.       else
  976.       if (instruc = A_MOVSB) or (instruc = A_MOVSBL)
  977.       or (instruc = A_MOVSBW) or (instruc = A_MOVSWL) then
  978.         instruc := A_MOVSX
  979.       else
  980.       if (instruc = A_MOVZB) or (instruc = A_MOVZWL)  then
  981.         instruc := A_MOVZX;
  982.  
  983.      With instr do
  984.          Begin
  985.            if operands[1].size = S_B then
  986.            Begin
  987.               if operands[2].size = S_L then
  988.                  opsize := S_BL
  989.               else
  990.               if operands[2].size = S_W then
  991.                  opsize := S_BW
  992.               else
  993.               begin
  994.                  Message(assem_e_invalid_size_movzx);
  995.                  exit;
  996.               end;
  997.            end
  998.            else
  999.            if operands[1].size = S_W then
  1000.            Begin
  1001.              if operands[2].size = S_L then
  1002.                 opsize := S_WL
  1003.              else
  1004.              begin
  1005.                  Message(assem_e_invalid_size_movzx);
  1006.                  exit;
  1007.              end;
  1008.            end
  1009.            else
  1010.            begin
  1011.                  Message(assem_e_invalid_size_movzx);
  1012.                  exit;
  1013.            end;
  1014.  
  1015.            if operands[1].operandtype = OPR_REGISTER then
  1016.            Begin
  1017.               if operands[2].operandtype <> OPR_REGISTER then
  1018.                  Message(assem_e_invalid_opcode) { exit...}
  1019.               else
  1020.                  p^.concat(new(pai386,op_reg_reg(instruc,opsize,
  1021.                    operands[1].reg,operands[2].reg)));
  1022.            end
  1023.            else
  1024.            if operands[1].operandtype = OPR_REFERENCE then
  1025.            Begin
  1026.               if operands[2].operandtype <> OPR_REGISTER then
  1027.                  Message(assem_e_invalid_opcode) {exit...}
  1028.               else
  1029.                  p^.concat(new(pai386,op_ref_reg(instruc,opsize,
  1030.                    newreference(operands[1].ref),operands[2].reg)));
  1031.            end
  1032.      end; { end with }
  1033.    end;
  1034.  
  1035.  
  1036.   Procedure ConcatOpCode(var instr: TInstruction);
  1037.   {*********************************************************************}
  1038.   { First Pass:                                                         }
  1039.   {    - If this is a three operand opcode:                             }
  1040.   {          imul,shld,and shrd  -> check them manually.                }
  1041.   {*********************************************************************}
  1042.   var
  1043.     fits : boolean;
  1044.     i: longint;
  1045.     opsize: topsize;
  1046.     optyp1, optyp2, optyp3: longint;
  1047.     instruc: tasmop;
  1048.   Begin
  1049.     fits := FALSE;
  1050.      for i:=1 to instr.numops do
  1051.      Begin
  1052.        case instr.operands[i].operandtype of
  1053.          OPR_REGISTER: instr.operands[i].size :=
  1054.                          _regsizes[instr.operands[i].reg];
  1055.        end; { end case }
  1056.      end; { endif }
  1057.     { setup specific instructions for first pass }
  1058.     instruc := instr.getinstruction;
  1059.  
  1060.     if (instruc in [A_LEA,A_LDS,A_LSS,A_LES,A_LFS,A_LGS]) then
  1061.     Begin
  1062.        if instr.operands[2].size <> S_L then
  1063.        Begin
  1064.          Message(assem_e_16bit_base_in_32bit_segment);
  1065.          exit;
  1066.        end; { endif }
  1067.     end;
  1068.  
  1069.     With instr do
  1070.     Begin
  1071.  
  1072.  
  1073.       for i:=1 to numops do
  1074.       Begin
  1075.          With operands[i] do
  1076.          Begin
  1077.          { check for 16-bit bases/indexes and emit an error.   }
  1078.          { we cannot only emit a warning since gas does not    }
  1079.          { accept 16-bit indexes and bases.                    }
  1080.           if (operandtype = OPR_REFERENCE) and
  1081.             ((ref.base <> R_NO) or
  1082.             (ref.index <> R_NO)) then
  1083.             Begin
  1084.             { index or base defined. }
  1085.               if (ref.base <> R_NO) then
  1086.               Begin
  1087.                 if not (ref.base in
  1088.                   [R_EAX,R_EBX,R_ECX,R_EDX,R_EBP,R_ESI,R_EDI,R_ESP]) then
  1089.                     Message(assem_e_16bit_base_in_32bit_segment);
  1090.               end;
  1091.             { index or base defined. }
  1092.               if (ref.index <> R_NO) then
  1093.               Begin
  1094.                   if not (ref.index in
  1095.                     [R_EAX,R_EBX,R_ECX,R_EDX,R_EBP,R_ESI,R_EDI,R_ESP]) then
  1096.                     Message(assem_e_16bit_index_in_32bit_segment);
  1097.               end;
  1098.             end;
  1099.             { Check for constants without bases/indexes in memory }
  1100.             { references.                                         }
  1101.             if (operandtype = OPR_REFERENCE) and
  1102.                (ref.base = R_NO) and
  1103.                (ref.index = R_NO) and
  1104.                (ref.symbol = nil) and
  1105.                (ref.offset <> 0) then
  1106.                Begin
  1107.                  ref.isintvalue := TRUE;
  1108.                  Message(assem_e_const_ref_not_allowed);
  1109.                end;
  1110.  
  1111.               opinfo := findtype(operands[i]);
  1112.  
  1113.           end; { end with }
  1114.       end; {endfor}
  1115.  
  1116.  
  1117.  
  1118.  
  1119.        { TAKE CARE OF SPECIAL OPCODES, TAKE CARE OF THEM INDIVUALLY.    }
  1120.        { ALL THE REST ARE TAKEN CARE BY OPCODE TABLE AND THIRD PASS.    }
  1121.        { is this right for ratti386 ? (PM) }
  1122.        { almost... here we check for the size of registers and references }
  1123.        { to determine the correct gas opcode to use, because if the token }
  1124.        { is A_MOVSX or A_MOVZX then that means that the person forgot to  }
  1125.        { specify the size..                                               }
  1126.        { if memory size is not specified, will of course give out an error}
  1127.        if instruc = A_MOVSX then
  1128.        Begin
  1129.          if numops = 2 then
  1130.          begin
  1131.            if stropsize = S_BL then
  1132.            begin
  1133.                operands[1].size := S_B;
  1134.                stropsize := S_NO;
  1135.                operands[2].size := S_L;
  1136.                addinstr(A_MOVSBL)
  1137.            end
  1138.            else
  1139.            if stropsize = S_WL then
  1140.            begin
  1141.                operands[1].size := S_W;
  1142.                stropsize := S_NO;
  1143.                operands[2].size := S_L;
  1144.                addinstr(A_MOVSWL)
  1145.            end
  1146.            else
  1147.            if stropsize = S_BW then
  1148.            begin
  1149.                operands[1].size := S_B;
  1150.                stropsize := S_NO;
  1151.                operands[2].size := S_W;
  1152.                addinstr(A_MOVSBW)
  1153.            end
  1154.            else
  1155.            if (operands[1].size = S_B) and (operands[2].size = S_W) then
  1156.                addinstr(A_MOVSBW)
  1157.            else
  1158.            if (operands[1].size = S_B) and (operands[2].size = S_L) then
  1159.                addinstr(A_MOVSBL)
  1160.            else
  1161.            if (operands[1].size = S_W) and (operands[2].size = S_L) then
  1162.                addinstr(A_MOVSWL)
  1163.            else
  1164.            begin
  1165.              Message(assem_e_invalid_size_movzx);
  1166.              exit;
  1167.            end;
  1168.            instruc := getinstruction; { reload instruction }
  1169.          end
  1170.          else
  1171.          begin
  1172.            Message(assem_e_too_many_operands);
  1173.            exit;
  1174.          end;
  1175.        end
  1176.        else
  1177.        if instruc = A_MOVZX then
  1178.        Begin
  1179.          if numops = 2 then
  1180.          Begin
  1181.            if stropsize = S_BW then
  1182.            begin
  1183.                operands[1].size := S_B;
  1184.                stropsize := S_NO;
  1185.                operands[2].size := S_W;
  1186.                addinstr(A_MOVZB)
  1187.            end
  1188.            else
  1189.            if stropsize = S_BL then
  1190.            begin
  1191.                operands[1].size := S_B;
  1192.                stropsize := S_NO;
  1193.                operands[2].size := S_L;
  1194.                addinstr(A_MOVZB)
  1195.            end
  1196.            else
  1197.            if stropsize = S_WL then
  1198.            begin
  1199.                operands[1].size := S_W;
  1200.                stropsize := S_NO;
  1201.                operands[2].size := S_L;
  1202.                addinstr(A_MOVZWL)
  1203.            end
  1204.            else
  1205.            { change the instruction to conform to GAS }
  1206.            if (operands[1].size = S_B) and (operands[2].size in [S_W,S_L]) then
  1207.                addinstr(A_MOVZB)
  1208.            else
  1209.            if (operands[1].size = S_W) and (operands[2].size = S_L) then
  1210.                addinstr(A_MOVZWL)
  1211.            else
  1212.            begin
  1213.              Message(assem_e_invalid_size_movzx);
  1214.              exit;
  1215.            end;
  1216.            instruc := getinstruction;  { reload instruction }
  1217.          end
  1218.          else
  1219.          Begin
  1220.            Message(assem_e_too_many_operands);
  1221.            exit;
  1222.          end;
  1223.        end
  1224.        else
  1225.        if instruc = A_FWAIT then
  1226.         FWaitWarning
  1227.        else
  1228.        if (instruc in [A_BT,A_BTC,A_BTR,A_BTS]) then
  1229.        Begin
  1230.           if numops = 2 then
  1231.             Begin
  1232.                 if (operands[1].operandtype = OPR_CONSTANT)
  1233.                 and (operands[1].val <= $ff) then
  1234.                   Begin
  1235.                      operands[1].opinfo := ao_imm8;
  1236.                      { no operand size if using constant. }
  1237.                      operands[1].size := S_NO;
  1238.                      fits := TRUE;
  1239.                   end
  1240.             end
  1241.           else
  1242.             Begin
  1243.                 Message(assem_e_invalid_opcode_and_operand);
  1244.                 exit;
  1245.             end;
  1246.        end
  1247.        else
  1248.        if instruc = A_ENTER then
  1249.        Begin
  1250.           if numops =2 then
  1251.             Begin
  1252.                if (operands[1].operandtype = OPR_CONSTANT) and
  1253.                   (operands[1].val <= $ffff) then
  1254.                   Begin
  1255.                      operands[1].opinfo := ao_imm16;
  1256.                   end  { endif }
  1257.             end { endif }
  1258.           else
  1259.             Begin
  1260.                 Message(assem_e_invalid_opcode_and_operand);
  1261.                 exit;
  1262.             end
  1263.        end { endif }
  1264.        else
  1265.      {  Handle special opcodes for the opcode   }
  1266.      {  table. Set them up correctly.           }
  1267.        if (instruc in [A_INS,A_IN]) then
  1268.        Begin
  1269.           if numops =2 then
  1270.             Begin
  1271.               if (operands[1].operandtype = OPR_REGISTER) and (operands[1].reg = R_DX)
  1272.                then
  1273.                Begin
  1274.                   operands[1].opinfo := ao_inoutportreg;
  1275.                   if (operands[2].operandtype = OPR_REGISTER) and
  1276.                     (operands[2].reg in [R_EAX,R_AX,R_AL]) and
  1277.                     (instruc = A_IN) then
  1278.                     Begin
  1279.                        operands[2].opinfo := ao_acc;
  1280.                     end
  1281.                end
  1282.               else
  1283.               if (operands[1].operandtype = OPR_CONSTANT) and (operands[1].val <= $ff)
  1284.                 and (instruc = A_IN) then
  1285.                 Begin
  1286.                   operands[1].opinfo := ao_imm8;
  1287.                   operands[1].size := S_B;
  1288.                  if (operands[2].operandtype = OPR_REGISTER) and
  1289.                     (operands[2].reg in [R_EAX,R_AX,R_AL]) and
  1290.                     (instruc = A_IN) then
  1291.                     Begin
  1292.                        operands[2].opinfo := ao_acc;
  1293.                     end
  1294.                 end;
  1295.             end
  1296.           else
  1297.             Begin
  1298.               Message(assem_e_invalid_opcode_and_operand);
  1299.               exit;
  1300.             end;
  1301.        end
  1302.        else
  1303.        if (instruc in [A_OUTS,A_OUT]) then
  1304.        Begin
  1305.           if numops =2 then
  1306.             Begin
  1307.               if (operands[2].operandtype = OPR_REGISTER) and (operands[2].reg = R_DX)
  1308.                then
  1309.                Begin
  1310.                   operands[2].opinfo := ao_inoutportreg;
  1311.                   if (operands[1].operandtype = OPR_REGISTER) and
  1312.                      (operands[1].reg in [R_EAX,R_AX,R_AL]) and
  1313.                      (instruc = A_OUT) then
  1314.                      Begin
  1315.                        operands[1].opinfo := ao_acc;
  1316.                        fits := TRUE;
  1317.                      end
  1318.                end
  1319.               else
  1320.               if (operands[2].operandtype = OPR_CONSTANT) and (operands[2].val <= $ff)
  1321.                 and (instruc = A_OUT) then
  1322.                 Begin
  1323.                   operands[2].opinfo := ao_imm8;
  1324.                   operands[2].size := S_B;
  1325.                   if (operands[1].operandtype = OPR_REGISTER) and
  1326.                      (operands[1].reg in [R_EAX,R_AX,R_AL]) and
  1327.                      (instruc = A_OUT) then
  1328.                      Begin
  1329.                        operands[1].opinfo := ao_acc;
  1330.                        fits := TRUE;
  1331.                      end
  1332.                 end;
  1333.             end
  1334.           else
  1335.             Begin
  1336.               Message(assem_e_invalid_opcode_and_operand);
  1337.               exit;
  1338.             end;
  1339.        end
  1340.        else
  1341.        if instruc in [A_RCL,A_RCR,A_ROL,A_ROR,A_SAL,A_SAR,A_SHL,A_SHR] then
  1342.        { if RCL,ROL,... }
  1343.        Begin
  1344.           if numops =2 then
  1345.             Begin
  1346.               if (operands[1].operandtype = OPR_REGISTER) and (operands[1].reg = R_CL)
  1347.               then
  1348.               Begin
  1349.                 operands[1].opinfo := ao_shiftcount
  1350.               end
  1351.               else
  1352.               if (operands[1].operandtype = OPR_CONSTANT) and
  1353.                 (operands[1].val <= $ff) then
  1354.                 Begin
  1355.                    operands[1].opinfo := ao_imm8;
  1356.                    operands[1].size := S_B;
  1357.                 end;
  1358.             end
  1359.           else { if numops = 2 }
  1360.             Begin
  1361.                 Message(assem_e_invalid_opcode_and_operand);
  1362.                 exit;
  1363.             end;
  1364.        end
  1365.        { endif ROL,RCL ... }
  1366.        else
  1367.        { this did not work  (PM) }
  1368.        if instruc in [A_DIV, A_IDIV] then
  1369.        Begin
  1370.           if (operands[2].operandtype = OPR_REGISTER) and
  1371.             (operands[2].reg in [R_AL,R_AX,R_EAX]) then
  1372.                 operands[2].opinfo := ao_acc;
  1373.        end
  1374.        else
  1375.        if (instruc = A_FNSTSW) or (instruc = A_FSTSW) then
  1376.        Begin
  1377.          { %ax can be omitted in ATT syntax }
  1378.           if numops = 0 then
  1379.             Begin
  1380.                numops:=1;
  1381.                operands[1].operandtype:=OPR_REGISTER;
  1382.                operands[1].reg:=R_AX;
  1383.                operands[1].opinfo := ao_acc;
  1384.             end
  1385.           else if numops = 1 then
  1386.             Begin
  1387.                 if (operands[1].operandtype = OPR_REGISTER) and
  1388.                   (operands[1].reg = R_AX) then
  1389.                  operands[1].opinfo := ao_acc;
  1390.             end
  1391.           else
  1392.             Begin
  1393.               Message(assem_e_invalid_opcode_and_operand);
  1394.               exit;
  1395.             end;
  1396.        end
  1397.        else
  1398.        if (instruc = A_SHLD) or (instruc = A_SHRD) then
  1399.        { these instruction are fully parsed individually on pass three }
  1400.        { so we just do a summary checking here.                        }
  1401.        Begin
  1402.           if numops = 3 then
  1403.             Begin
  1404.                 if (operands[3].operandtype = OPR_CONSTANT)
  1405.                 and (operands[3].val <= $ff) then
  1406.                 Begin
  1407.                    operands[3].opinfo := ao_imm8;
  1408.                    operands[3].size := S_B;
  1409.                 end;
  1410.             end
  1411.           else
  1412.             Begin
  1413.                 Message(assem_e_invalid_opcode_and_operand);
  1414.                 exit;
  1415.             end;
  1416.        end
  1417.        else
  1418.        if instruc = A_INT then
  1419.        Begin
  1420.           if numops = 1 then
  1421.             Begin
  1422.                if (operands[1].operandtype = OPR_CONSTANT) and
  1423.                  (operands[1].val <= $ff) then
  1424.                       operands[1].opinfo := ao_imm8;
  1425.             end
  1426.        end
  1427.        else
  1428.        if instruc = A_RET then
  1429.        Begin
  1430.           if numops =1 then
  1431.             Begin
  1432.                if (operands[1].operandtype = OPR_CONSTANT) and
  1433.                   (operands[1].val <= $ffff) then
  1434.                     operands[1].opinfo := ao_imm16;
  1435.             end
  1436.        end; { endif }
  1437.  
  1438.        { all string instructions have default memory }
  1439.        { location which are ignored. Take care of    }
  1440.        { those.                                      }
  1441.        { Here could be added the code for segment    }
  1442.        { overrides.                                  }
  1443.        if instruc in [A_SCAS,A_CMPS,A_STOS,A_LODS] then
  1444.        Begin
  1445.           if numops =1 then
  1446.             Begin
  1447.                if (operands[1].operandtype = OPR_REFERENCE) and
  1448.                  (assigned(operands[1].ref.symbol)) then
  1449.                  Freemem(operands[1].ref.symbol,length(operands[1].ref.symbol^)+1);
  1450.                operands[1].operandtype := OPR_NONE;
  1451.                numops := 0;
  1452.             end;
  1453.        end; { endif }
  1454.        if instruc in [A_INS,A_MOVS,A_OUTS] then
  1455.        Begin
  1456.           if numops =2 then
  1457.             Begin
  1458.                if (operands[2].operandtype = OPR_REFERENCE) and
  1459.                  (assigned(operands[2].ref.symbol)) then
  1460.                  Freemem(operands[2].ref.symbol,length(operands[2].ref.symbol^)+1);
  1461.                if (operands[1].operandtype = OPR_REFERENCE) and
  1462.                  (assigned(operands[1].ref.symbol)) then
  1463.                  Freemem(operands[1].ref.symbol,length(operands[2].ref.symbol^)+1);
  1464.                operands[2].operandtype := OPR_NONE;
  1465.                operands[1].operandtype := OPR_NONE;
  1466.                numops := 0;
  1467.             end;
  1468.        end;
  1469.      { handle parameter for segment overrides }
  1470.      if instruc = A_XLAT then
  1471.      Begin
  1472.         { handle special TP syntax case for XLAT }
  1473.         { here we accept XLAT, XLATB and XLAT m8 }
  1474.         if (numops = 1) or (numops = 0) then
  1475.          Begin
  1476.                if (operands[1].operandtype = OPR_REFERENCE) and
  1477.                  (assigned(operands[1].ref.symbol)) then
  1478.                  Freemem(operands[1].ref.symbol,length(operands[1].ref.symbol^)+1);
  1479.                operands[1].operandtype := OPR_NONE;
  1480.                numops := 0;
  1481.                { always a byte for XLAT }
  1482.                instr.stropsize := S_B;
  1483.          end;
  1484.      end
  1485.      else
  1486.      { ------------------------------------------------------------------- }
  1487.      { ------------------------- SIZE CHECK ------------------------------ }
  1488.      { ------------- presently done only for most used opcodes  ---------- }
  1489.      {  Checks if the suffix concords with the destination size    , if    }
  1490.      {  not gives out an error. (This check is stricter then gas but is    }
  1491.      {  REQUIRED for intasmi3)                                             }
  1492.      if instruc in [A_MOV,A_ADD,A_SUB,A_ADC,A_SBB,A_CMP,A_AND,A_OR,A_TEST,A_XOR] then
  1493.      begin
  1494.        if (instr.stropsize <> S_NO) and (instr.operands[2].size <> S_NO) then
  1495.          if (instr.stropsize <> instr.operands[2].size) then
  1496.          begin
  1497.             Message(assem_e_size_suffix_and_dest_reg_dont_match);
  1498.             exit;
  1499.          end;
  1500.      end
  1501.      else
  1502.      if instruc in [A_DEC,A_INC,A_NOT,A_NEG] then
  1503.      begin
  1504.        if (instr.stropsize <> S_NO) and (instr.operands[1].size <> S_NO) then
  1505.          if (instr.stropsize <> instr.operands[1].size) then
  1506.          begin
  1507.             Message(assem_e_size_suffix_and_dest_reg_dont_match);
  1508.             exit;
  1509.          end;
  1510.      end;
  1511.      { ------------------------------------------------------------------- }
  1512.  
  1513.  
  1514.     { copy them to local variables }
  1515.     { for faster access            }
  1516.     optyp1:=operands[1].opinfo;
  1517.     optyp2:=operands[2].opinfo;
  1518.     optyp3:=operands[3].opinfo;
  1519.  
  1520.     end; { end with }
  1521.  
  1522.     { after reading the operands }
  1523.     { search the instruction     }
  1524.     { setup startvalue from cache }
  1525.     if ins_cache[instruc]<>-1 then
  1526.        i:=ins_cache[instruc]
  1527.     else i:=0;
  1528.  
  1529.     { I think this is too dangerous for me therefore i decided that for }
  1530.     { the att version only if the processor > i386 or we are compiling  }
  1531.     { the system unit then this will be allowed...                      }
  1532.     if (instruc >= lastop_in_table) and
  1533.        ((cs_compilesystem in aktswitches) or (opt_processors > globals.i386)) then
  1534.       begin
  1535.          Message1(assem_w_opcode_not_in_table,att_op2str[instruc]);
  1536.          fits:=true;
  1537.       end
  1538.     else while not(fits) do
  1539.       begin
  1540.        { set the instruction cache, if the instruction }
  1541.        { occurs the first time                         }
  1542.        if (it[i].i=instruc) and (ins_cache[instruc]=-1) then
  1543.            ins_cache[instruc]:=i;
  1544.  
  1545.        if (it[i].i=instruc) and (instr.numops=it[i].ops) then
  1546.        begin
  1547.           { first fit }
  1548.           case instr.numops of
  1549.           0 : begin
  1550.                  fits:=true;
  1551.                  break;
  1552.               end;
  1553.           1 :
  1554.               Begin
  1555.                 if (optyp1 and it[i].o1)<>0 then
  1556.                 Begin
  1557.                    fits:=true;
  1558.                    break;
  1559.                 end;
  1560.                 { I consider sign-extended 8bit value to }
  1561.                 { be equal to immediate 8bit therefore   }
  1562.                 { convert...                             }
  1563.                 if (optyp1 = ao_imm8) then
  1564.                 Begin
  1565.                   { check if this is a simple sign extend. }
  1566.                   if (it[i].o1<>ao_imm8s) then
  1567.                   Begin
  1568.                     fits:=true;
  1569.                     break;
  1570.                   end;
  1571.                 end;
  1572.               end;
  1573.           2 : if ((optyp1 and it[i].o1)<>0) and
  1574.                ((optyp2 and it[i].o2)<>0) then
  1575.                Begin
  1576.                      fits:=true;
  1577.                      break;
  1578.                end
  1579.                { if the operands can be swaped }
  1580.                { then swap them                }
  1581.                else if ((it[i].m and af_d)<>0) and
  1582.                ((optyp1 and it[i].o2)<>0) and
  1583.                ((optyp2 and it[i].o1)<>0) then
  1584.                begin
  1585.                  fits:=true;
  1586.                  break;
  1587.                end;
  1588.           3 : if ((optyp1 and it[i].o1)<>0) and
  1589.                ((optyp2 and it[i].o2)<>0) and
  1590.                ((optyp3 and it[i].o3)<>0) then
  1591.                Begin
  1592.                  fits:=true;
  1593.                  break;
  1594.                end;
  1595.           end; { end case }
  1596.        end; { endif }
  1597.        if it[i].i=A_NONE then
  1598.        begin
  1599.          { NO MATCH! }
  1600.          Message(assem_e_invalid_opcode_and_operand);
  1601.          exit;
  1602.        end;
  1603.        inc(i);
  1604.       end; { end while }
  1605.  
  1606.   { We add the opcode to the opcode linked list }
  1607.   if fits then
  1608.   Begin
  1609.     if instr.getprefix <> A_NONE then
  1610.     Begin
  1611.       p^.concat(new(pai386,op_none(instr.getprefix,S_NO)));
  1612.     end;
  1613.     { change from AT&T styled floating point to   }
  1614.     { intel styled floating point with valid size }
  1615.     { we use these instructions so it does not    }
  1616.     { mess up intasmi3                            }
  1617.     if (instruc >= A_FILDQ) and (instruc <= A_FIDIVRS) then
  1618.     Begin
  1619.       instr.stropsize := _fpusizes[instruc];
  1620.       instr.addinstr(_fpuopcodes[instruc]);
  1621.       instruc := instr.getinstruction;
  1622.     end;
  1623.  
  1624.     case instr.numops of
  1625.      0:
  1626.         if instr.stropsize <> S_NO then
  1627.         { is this a string operation opcode or xlat then check }
  1628.         { the size of the operation.                           }
  1629.           p^.concat(new(pai386,op_none(instruc,instr.stropsize)))
  1630.         else
  1631.           p^.concat(new(pai386,op_none(instruc,S_NO)));
  1632.      1: Begin
  1633.           case instr.operands[1].operandtype of
  1634.                { all one operand opcodes with constant have no defined sizes }
  1635.                { at least that is what it seems in the tasm 2.0 manual.      }
  1636.            OPR_CONSTANT:  p^.concat(new(pai386,op_const(instruc,
  1637.                              S_NO, instr.operands[1].val)));
  1638.            OPR_REGISTER: if instruc in [A_INC,A_DEC, A_NEG,A_NOT] then
  1639.                          Begin
  1640.                            p^.concat(new(pai386,op_reg(instruc,
  1641.                                instr.operands[1].size,instr.operands[1].reg)));
  1642.                          end
  1643.                          else
  1644.                            p^.concat(new(pai386,op_reg(instruc,
  1645.                                S_NO,instr.operands[1].reg)));
  1646.            OPR_REFERENCE:
  1647.                { now first check suffix ... }
  1648.                           if instr.stropsize <> S_NO then
  1649.                           Begin
  1650.                                 p^.concat(new(pai386,op_ref(instruc,
  1651.                                   instr.stropsize,newreference(instr.operands[1].ref))));
  1652.                           end
  1653.                { no suffix... therefore resort using intel styled checking .. }
  1654.                           else
  1655.                           if (instr.operands[1].size <> S_NO) and NOT (instruc in [A_CALL,A_JMP]) then
  1656.                           Begin
  1657.                            p^.concat(new(pai386,op_ref(instruc,
  1658.                             instr.operands[1].size,newreference(instr.operands[1].ref))));
  1659.                           end
  1660.                           else
  1661.                           Begin
  1662.                               { special jmp and call case with }
  1663.                               { symbolic references.           }
  1664.                               if (instruc in [A_CALL,A_JMP]) or
  1665.                                  (instruc = A_FNSTCW) or
  1666.                                  (instruc = A_FSTCW) or
  1667.                                  (instruc = A_FLDCW) or
  1668.                                  (instruc = A_FNSTSW) or
  1669.                                  (instruc = A_FSTSW) or
  1670.                                  (instruc = A_FLDENV) or
  1671.                                  (instruc = A_FSTENV) or
  1672.                                  (instruc = A_FNSAVE) or
  1673.                                  (instruc = A_FSAVE) then
  1674.                               Begin
  1675.                                 p^.concat(new(pai386,op_ref(instruc,
  1676.                                   S_NO,newreference(instr.operands[1].ref))));
  1677.                               end
  1678.                               else
  1679.                                 Message(assem_e_invalid_opcode_and_operand);
  1680.                           end;
  1681. { This either crashed the compiler or the symbol would always be nil! }
  1682. { The problem is here is I didn't see any way of adding the labeled   }
  1683. { symbol in the internal list, since i think from what i see in aasm  }
  1684. { that these will automatically be declared as external ??            }
  1685. {                              if (instruc in [A_JO,A_JNO,A_JB,A_JC,A_JNAE,
  1686.                                 A_JNB,A_JNC,A_JAE,A_JE,A_JZ,A_JNE,A_JNZ,A_JBE,A_JNA,A_JNBE,
  1687.                                 A_JA,A_JS,A_JNS,A_JP,A_JPE,A_JNP,A_JPO,A_JL,A_JNGE,A_JNL,A_JGE,
  1688.                                 A_JLE,A_JNG,A_JNLE,A_JG,A_JCXZ,A_JECXZ,A_LOOP,A_LOOPZ,A_LOOPE,
  1689.                                 A_LOOPNZ,A_LOOPNE,A_JMP,A_CALL]) then
  1690.                               Begin
  1691.                                 if assigned(instr.operands[1].ref.symbol) then
  1692.                                    p^.concat(new(pai386,op_csymbol(instruc,
  1693.                                      S_NO,newcsymbol(instr.operands[1].ref.symbol^,instr.operands[1].ref.offset))))
  1694.                                 else
  1695.                                   Message(assem_e_invalid_opcode_and_operand);
  1696.                               end
  1697.                               else
  1698.                               else
  1699.                                 Message(assem_e_invalid_opcode_and_operand);
  1700.                           end;}
  1701.            OPR_NONE: Begin
  1702.                        Message(assem_f_internal_error_in_concatopcode);
  1703.                      end;
  1704.           else
  1705.            Begin
  1706.              Message(assem_f_internal_error_in_concatopcode);
  1707.            end;
  1708.           end;
  1709.         end;
  1710.      2:
  1711.         Begin
  1712.            if instruc in [A_MOVSX,A_MOVZX,A_MOVSB,A_MOVSBL,A_MOVSBW,
  1713.              A_MOVSWL,A_MOVZB,A_MOVZWL] then
  1714.               { movzx and movsx }
  1715.               HandleExtend(instr)
  1716.            else
  1717.              { other instructions }
  1718.              Begin
  1719.                 With instr do
  1720.                 Begin
  1721.                 { source }
  1722.                   opsize := operands[1].size;
  1723.                   case operands[1].operandtype of
  1724.                   { reg,reg     }
  1725.                   { reg,ref     }
  1726.                   { const,reg -- IN/OUT }
  1727.                    OPR_REGISTER:
  1728.                      Begin
  1729.                        case operands[2].operandtype of
  1730.                          OPR_REGISTER:
  1731.                             { correction: according to the DJGPP FAQ, gas }
  1732.                             { doesn't even check correctly the size of    }
  1733.                             { operands, therefore let us specify a size!  }
  1734.                             { as in the GAS docs... destination tells us  }
  1735.                             { the size! This might give out invalid output }
  1736.                             { in some very rare cases (because the size   }
  1737.                             { checking is still not perfect).             }
  1738.                             if (opsize = operands[2].size) then
  1739.                             begin
  1740.                                p^.concat(new(pai386,op_reg_reg(instruc,
  1741.                                opsize,operands[1].reg,operands[2].reg)));
  1742.                             end
  1743.                             else
  1744.                             { these do not require any size specification. }
  1745.                             if (instruc in [A_IN,A_OUT,A_SAL,A_SAR,A_SHL,A_SHR,A_ROL,
  1746.                                A_ROR,A_RCR,A_RCL])  then
  1747.                                { outs and ins are already taken care by }
  1748.                                { the first pass.                        }
  1749.                                p^.concat(new(pai386,op_reg_reg(instruc,
  1750.                                S_NO,operands[1].reg,operands[2].reg)))
  1751.                             else
  1752.                             if stropsize <> S_NO then
  1753.                             Begin
  1754.                                p^.concat(new(pai386,op_reg_reg(instruc,
  1755.                                stropsize,operands[1].reg,operands[2].reg)))
  1756.                             end
  1757.                             else
  1758.                             Begin
  1759.                               Message(assem_e_invalid_opcode_and_operand);
  1760.                             end;
  1761.                          OPR_REFERENCE:
  1762.                            { variable name. }
  1763.                            { here we must check the instruction type }
  1764.                            { before deciding if to use and compare   }
  1765.                            { any sizes.                              }
  1766.                            if assigned(operands[2].ref.symbol) then
  1767.                            Begin
  1768.                               if stropsize <> S_NO then
  1769.                               Begin
  1770.                                p^.concat(new(pai386,op_reg_ref(instruc,
  1771.                                stropsize,operands[1].reg,newreference(operands[2].ref))))
  1772.                               end
  1773.                               else
  1774.                               if (opsize = operands[2].size) or (instruc in
  1775.                                [A_RCL,A_RCR,A_ROL,A_ROR,A_SAL,A_SAR,A_SHR,A_SHL]) then
  1776.                                   p^.concat(new(pai386,op_reg_ref(instruc,
  1777.                                   opsize,operands[1].reg,newreference(operands[2].ref))))
  1778.                               else
  1779.                                   Message(assem_e_invalid_size_in_ref);
  1780.                            end
  1781.                            else
  1782.                            Begin
  1783.                               { register reference }
  1784.                               if stropsize <> S_NO then
  1785.                               Begin
  1786.                                p^.concat(new(pai386,op_reg_ref(instruc,
  1787.                                stropsize,operands[1].reg,newreference(operands[2].ref))))
  1788.                               end
  1789.                               else
  1790.                               if (opsize = operands[2].size) or  (operands[2].size = S_NO) then
  1791.                                   p^.concat(new(pai386,op_reg_ref(instruc,
  1792.                                   opsize,operands[1].reg,newreference(operands[2].ref))))
  1793.                               else
  1794.                                   Message(assem_e_invalid_size_in_ref);
  1795.                            end;
  1796.                          OPR_CONSTANT:  { OUT }
  1797.                            begin
  1798.                               { determine first with suffix }
  1799.                               if instruc = A_OUT then
  1800.                               begin
  1801.                                if instr.stropsize <> S_NO then
  1802.                                   p^.concat(new(pai386,op_reg_const(instruc,stropsize,
  1803.                                     instr.operands[1].reg, instr.operands[2].val)))
  1804.                                else
  1805.                                   p^.concat(new(pai386,op_reg_const(instruc,S_NO,
  1806.                                     instr.operands[1].reg, instr.operands[2].val)));
  1807.                               end
  1808.                               else
  1809.                                 Message(assem_e_invalid_opcode);
  1810.                            end;
  1811.                        else { else case }
  1812.                          Begin
  1813.                            Message(assem_f_internal_error_in_concatopcode);
  1814.                          end;
  1815.                        end; { end inner case }
  1816.                      end;
  1817.                   { const,reg   }
  1818.                   { const,const }
  1819.                   { const,ref   }
  1820.                    OPR_CONSTANT:
  1821.                       case instr.operands[2].operandtype of
  1822.                       { constant, constant does not have a specific size. }
  1823.                         OPR_CONSTANT:
  1824.                            p^.concat(new(pai386,op_const_const(instruc,
  1825.                            S_NO,operands[1].val,operands[2].val)));
  1826.                         OPR_REFERENCE:
  1827.                            Begin
  1828.                            { check for suffix first ... }
  1829.                               if (instr.stropsize <> S_NO) then
  1830.                               Begin
  1831.                                  p^.concat(new(pai386,op_const_ref(instruc,
  1832.                                  stropsize,operands[1].val,
  1833.                                  newreference(operands[2].ref))))
  1834.                               end
  1835.                               else
  1836.                            { resort to intel styled checking ... }
  1837.                               if (operands[1].val <= $ff) and
  1838.                                (operands[2].size in [S_B,S_W,S_L,S_Q,S_S]) then
  1839.                                  p^.concat(new(pai386,op_const_ref(instruc,
  1840.                                  operands[2].size,operands[1].val,
  1841.                                  newreference(operands[2].ref))))
  1842.                               else
  1843.                               if (operands[1].val <= $ffff) and
  1844.                                (operands[2].size in [S_W,S_L,S_Q,S_S]) then
  1845.                                  p^.concat(new(pai386,op_const_ref(instruc,
  1846.                                  operands[2].size,operands[1].val,
  1847.                                  newreference(operands[2].ref))))
  1848.                               else
  1849.                               if (operands[1].val <= $7fffffff) and
  1850.                                (operands[2].size in [S_L,S_Q,S_S]) then
  1851.                                  p^.concat(new(pai386,op_const_ref(instruc,
  1852.                                  operands[2].size,operands[1].val,
  1853.                                  newreference(operands[2].ref))))
  1854.                               else
  1855.                                  Message(assem_e_invalid_size_in_ref);
  1856.                            end;
  1857.                         OPR_REGISTER:
  1858.                            Begin
  1859.                               { size of opcode determined by register }
  1860.                               if (operands[1].val <= $ff) and
  1861.                                (operands[2].size in [S_B,S_W,S_L,S_Q,S_S]) then
  1862.                                  p^.concat(new(pai386,op_const_reg(instruc,
  1863.                                  operands[2].size,operands[1].val,
  1864.                                  operands[2].reg)))
  1865.                               else
  1866.                               if (operands[1].val <= $ffff) and
  1867.                                (operands[2].size in [S_W,S_L,S_Q,S_S]) then
  1868.                                  p^.concat(new(pai386,op_const_reg(instruc,
  1869.                                  operands[2].size,operands[1].val,
  1870.                                  operands[2].reg)))
  1871.                               else
  1872.                               if (operands[1].val <= $7fffffff) and
  1873.                                (operands[2].size in [S_L,S_Q,S_S]) then
  1874.                                  p^.concat(new(pai386,op_const_reg(instruc,
  1875.                                  operands[2].size,operands[1].val,
  1876.                                  operands[2].reg)))
  1877.                               else
  1878.                                Message(assem_e_invalid_opcode_size);
  1879.                            end;
  1880.                       else
  1881.                          Begin
  1882.                            Message(assem_f_internal_error_in_concatopcode);
  1883.                          end;
  1884.                       end; { end case }
  1885.                    { ref,reg     }
  1886.                    { ref,ref     }
  1887.                    OPR_REFERENCE:
  1888.                       case instr.operands[2].operandtype of
  1889.                          OPR_REGISTER:
  1890.                             if assigned(operands[1].ref.symbol) then
  1891.                             { global variable }
  1892.                             Begin
  1893.                               if instruc in [A_LEA,A_LDS,A_LES,A_LFS,A_LGS,A_LSS]
  1894.                                then
  1895.                                  p^.concat(new(pai386,op_ref_reg(instruc,
  1896.                                  S_NO,newreference(operands[1].ref),
  1897.                                  operands[2].reg)))
  1898.                               else
  1899.                               if (stropsize <> S_NO) then
  1900.                               Begin
  1901.                                  p^.concat(new(pai386,op_ref_reg(instruc,
  1902.                                  stropsize,newreference(operands[1].ref),
  1903.                                  operands[2].reg)))
  1904.                               end
  1905.                               else
  1906.                               if (opsize = operands[2].size) then
  1907.                                  p^.concat(new(pai386,op_ref_reg(instruc,
  1908.                                  opsize,newreference(operands[1].ref),
  1909.                                  operands[2].reg)))
  1910.                               else
  1911.                                 Begin
  1912.                                    Message(assem_e_invalid_opcode_and_operand);
  1913.                                 end;
  1914.                             end
  1915.                             else
  1916.                             Begin
  1917.                               { register reference }
  1918.                               { possiblities:1) local variable which }
  1919.                               { has been replaced by bp and offset   }
  1920.                               { in this case size should be valid    }
  1921.                               {              2) Indirect register    }
  1922.                               { adressing, 2nd operand determines    }
  1923.                               { size.                                }
  1924.                               if (stropsize <> S_NO) then
  1925.                               Begin
  1926.                                  p^.concat(new(pai386,op_ref_reg(instruc,
  1927.                                  stropsize,newreference(operands[1].ref),
  1928.                                  operands[2].reg)))
  1929.                               end
  1930.                               else
  1931.                               if (opsize = operands[2].size) or (opsize = S_NO) then
  1932.                               Begin
  1933.                                  p^.concat(new(pai386,op_ref_reg(instruc,
  1934.                                  operands[2].size,newreference(operands[1].ref),
  1935.                                  operands[2].reg)));
  1936.                               end
  1937.                               else
  1938.                                 Message(assem_e_invalid_size_in_ref);
  1939.                             end;
  1940.                          OPR_REFERENCE: { special opcodes }
  1941.                             p^.concat(new(pai386,op_ref_ref(instruc,
  1942.                             opsize,newreference(operands[1].ref),
  1943.                             newreference(operands[2].ref))));
  1944.                       else
  1945.                          Begin
  1946.                            Message(assem_f_internal_error_in_concatopcode);
  1947.                          end;
  1948.                    end; { end inner case }
  1949.                   end; { end case }
  1950.                 end; { end with }
  1951.              end; {end if movsx... }
  1952.         end;
  1953.      3: Begin
  1954.              { only imul, shld and shrd  }
  1955.              { middle must be a register }
  1956.              if (instruc in [A_SHLD,A_SHRD]) and (instr.operands[2].operandtype =
  1957.                 OPR_REGISTER) then
  1958.              Begin
  1959.                case instr.operands[2].size of
  1960.                 S_W:  if instr.operands[1].operandtype = OPR_CONSTANT then
  1961.                         Begin
  1962.                           if instr.operands[1].val <= $ff then
  1963.                             Begin
  1964.                               if instr.operands[3].size in [S_W] then
  1965.                               Begin
  1966.                                  case instr.operands[3].operandtype of
  1967.                                   OPR_REFERENCE: { MISSING !!!! } ;
  1968.                                   OPR_REGISTER:  p^.concat(new(pai386,
  1969.                                      op_const_reg_reg(instruc, S_W,
  1970.                                      instr.operands[1].val, instr.operands[2].reg,
  1971.                                      instr.operands[3].reg)));
  1972.                                  else
  1973.                                     Message(assem_e_invalid_opcode_and_operand);
  1974.                                  end;
  1975.                               end
  1976.                               else
  1977.                                  Message(assem_e_invalid_opcode_and_operand);
  1978.                             end;
  1979.                         end
  1980.                       else
  1981.                         Message(assem_e_invalid_opcode_and_operand);
  1982.                 S_L:  if instr.operands[1].operandtype = OPR_CONSTANT then
  1983.                         Begin
  1984.                           if instr.operands[1].val <= $ff then
  1985.                             Begin
  1986.                               if instr.operands[3].size in [S_L] then
  1987.                               Begin
  1988.                                  case instr.operands[3].operandtype of
  1989.                                   OPR_REFERENCE: { MISSING !!!! } ;
  1990.                                   OPR_REGISTER:  p^.concat(new(pai386,
  1991.                                      op_const_reg_reg(instruc, S_L,
  1992.                                      instr.operands[1].val, instr.operands[2].reg,
  1993.                                      instr.operands[3].reg)));
  1994.                                  else
  1995.                                    Message(assem_e_invalid_opcode_and_operand);
  1996.                                  end;
  1997.                               end
  1998.                               else
  1999.                                 Message(assem_e_invalid_opcode_and_operand);
  2000.                             end;
  2001.                         end
  2002.                       else
  2003.                        Message(assem_e_invalid_opcode_and_operand);
  2004.                 else
  2005.                   Message(assem_e_invalid_opcode_and_operand);
  2006.                end; { end case }
  2007.              end
  2008.              else
  2009.              if (instruc in [A_IMUL]) and (instr.operands[3].operandtype
  2010.                = OPR_REGISTER) then
  2011.              Begin
  2012.                case instr.operands[3].size of
  2013.                 S_W:  if instr.operands[1].operandtype = OPR_CONSTANT then
  2014.                         Begin
  2015.                           if instr.operands[1].val <= $ffff then
  2016.                             Begin
  2017.                               if instr.operands[2].size in [S_W] then
  2018.                               Begin
  2019.                                  case instr.operands[2].operandtype of
  2020.                                   OPR_REFERENCE: { MISSING !!!! } ;
  2021.                                   OPR_REGISTER:  p^.concat(new(pai386,
  2022.                                      op_const_reg_reg(instruc, S_W,
  2023.                                      instr.operands[1].val, instr.operands[2].reg,
  2024.                                      instr.operands[3].reg)));
  2025.                                  else
  2026.                                   Message(assem_e_invalid_opcode_and_operand);
  2027.                                  end; { end case }
  2028.                               end
  2029.                               else
  2030.                                 Message(assem_e_invalid_opcode_and_operand);
  2031.                             end;
  2032.                         end
  2033.                       else
  2034.                         Message(assem_e_invalid_opcode_and_operand);
  2035.                 S_L:  if instr.operands[1].operandtype = OPR_CONSTANT then
  2036.                         Begin
  2037.                           if instr.operands[1].val <= $7fffffff then
  2038.                             Begin
  2039.                               if instr.operands[2].size in [S_L] then
  2040.                               Begin
  2041.                                  case instr.operands[2].operandtype of
  2042.                                   OPR_REFERENCE: { MISSING !!!! } ;
  2043.                                   OPR_REGISTER:  p^.concat(new(pai386,
  2044.                                      op_const_reg_reg(instruc, S_L,
  2045.                                      instr.operands[1].val, instr.operands[2].reg,
  2046.                                      instr.operands[3].reg)));
  2047.                                  else
  2048.                                    Message(assem_e_invalid_opcode_and_operand);
  2049.                                  end; { end case }
  2050.                               end
  2051.                               else
  2052.                                Message(assem_e_invalid_opcode_and_operand);
  2053.                             end;
  2054.                         end
  2055.                       else
  2056.                        Message(assem_e_invalid_opcode_and_operand);
  2057.                 else
  2058.                   Message(assem_e_invalid_middle_sized_operand);
  2059.                end; { end case }
  2060.              end { endif }
  2061.              else
  2062.                Message(assem_e_invalid_three_operand_opcode);
  2063.         end;
  2064.   end; { end case }
  2065.  end;
  2066.  end;
  2067.  
  2068.     Procedure ConcatLabeledInstr(var instr: TInstruction);
  2069.  
  2070.       Var instruct : tasmop;
  2071.           i : longint;
  2072.     Begin
  2073.        instruct:=instr.getinstruction;
  2074.        if (instruct in [A_JO,A_JNO,A_JB,A_JC,A_JNAE,
  2075.         A_JNB,A_JNC,A_JAE,A_JE,A_JZ,A_JNE,A_JNZ,A_JBE,A_JNA,A_JNBE,
  2076.         A_JA,A_JS,A_JNS,A_JP,A_JPE,A_JNP,A_JPO,A_JL,A_JNGE,A_JNL,A_JGE,
  2077.         A_JLE,A_JNG,A_JNLE,A_JG,A_JCXZ,A_JECXZ,A_LOOP,A_LOOPZ,A_LOOPE,
  2078.         A_LOOPNZ,A_LOOPNE,A_MOV,A_JMP,A_CALL]) then
  2079.        Begin
  2080.         if (instr.numops <> 1) then
  2081.           Message(assem_e_invalid_labeled_opcode)
  2082.         else if instr.operands[1].operandtype <> OPR_LABINSTR then
  2083.           Message(assem_e_invalid_labeled_opcode)
  2084.         else if assigned(instr.operands[1].hl) then
  2085.           ConcatLabel(p,instruct, instr.operands[1].hl)
  2086.         else
  2087.           Begin
  2088.             Message(assem_f_internal_error_in_concatlabeledinstr);
  2089.           end;
  2090.        end
  2091.        else
  2092.        if (cs_compilesystem in aktswitches) then
  2093.        begin
  2094.         for i:=1 to instr.numops do
  2095.           if instr.operands[i].operandtype=OPR_LABINSTR then
  2096.             begin
  2097.               instr.operands[i].operandtype:=OPR_REFERENCE;
  2098.               instr.operands[i].ref.symbol:=newpasstr(lab2str(instr.operands[i].hl) );
  2099.               instr.operands[i].opinfo:=ao_mem;
  2100.               instr.operands[i].ref.base:=R_NO;
  2101.               instr.operands[i].ref.index:=R_NO;
  2102.               instr.operands[i].ref.segment:=R_DEFAULT_SEG;
  2103.               instr.operands[i].ref.offset:=0;
  2104.             end;
  2105.         { handle now as an ordinary opcode }
  2106.         concatopcode(instr);
  2107.        end
  2108.        else
  2109.          Message(assem_e_invalid_operand);
  2110.     end;
  2111.  
  2112.  
  2113.  
  2114.   {---------------------------------------------------------------------}
  2115.   {                     Routines for the parsing                        }
  2116.   {---------------------------------------------------------------------}
  2117.  
  2118.      procedure consume(t : tinteltoken);
  2119.  
  2120.      begin
  2121.        if t<>actasmtoken then
  2122.         Message(assem_e_syntax_error);
  2123.        actasmtoken:=gettoken;
  2124.        { if the token must be ignored, then }
  2125.        { get another token to parse.        }
  2126.        if actasmtoken = AS_NONE then
  2127.           actasmtoken := gettoken;
  2128.       end;
  2129.  
  2130.  
  2131.  
  2132.  
  2133.  
  2134.    function findregister(const s : string): tregister;
  2135.   {*********************************************************************}
  2136.   { FUNCTION findregister(s: string):tasmop;                            }
  2137.   {  Description: Determines if the s string is a valid register,       }
  2138.   {  if so returns correct tregister token, or R_NO if not found.       }
  2139.   {*********************************************************************}
  2140.    var
  2141.     i: tregister;
  2142.    begin
  2143.      findregister := R_NO;
  2144.      for i:=firstreg to lastreg do
  2145.        if s = iasmregs[i] then
  2146.        Begin
  2147.          findregister := i;
  2148.          exit;
  2149.        end;
  2150.    end;
  2151.  
  2152.  
  2153.  
  2154.    function findprefix(const s: string; var token: tasmop): boolean;
  2155.    var i: byte;
  2156.    Begin
  2157.      findprefix := FALSE;
  2158.      for i:=0 to _count_asmprefixes do
  2159.      Begin
  2160.        if s = _asmprefixes[i] then
  2161.        begin
  2162.           token := _prefixtokens[i];
  2163.           findprefix := TRUE;
  2164.           exit;
  2165.        end;
  2166.      end;
  2167.    end;
  2168.  
  2169.  
  2170.    function findsegment(const s:string): tregister;
  2171.   {*********************************************************************}
  2172.   { FUNCTION findsegment(s: string):tasmop;                             }
  2173.   {  Description: Determines if the s string is a valid segment register}
  2174.   {  if so returns correct tregister token, or R_NO if not found.       }
  2175.   {*********************************************************************}
  2176.    var
  2177.     i: tregister;
  2178.    Begin
  2179.      findsegment := R_DEFAULT_SEG;
  2180.      for i:=firstsreg to lastsreg do
  2181.        if s = iasmregs[i] then
  2182.        Begin
  2183.          findsegment := i;
  2184.          exit;
  2185.        end;
  2186.    end;
  2187.  
  2188.  
  2189.    function findopcode(const s: string): tasmop;
  2190.   {*********************************************************************}
  2191.   { FUNCTION findopcode(s: string): tasmop;                             }
  2192.   {  Description: Determines if the s string is a valid opcode          }
  2193.   {  if so returns correct tasmop token.                                }
  2194.   {*********************************************************************}
  2195.    var
  2196.     i: tasmop;
  2197.     j: byte;
  2198.     hs: topsize;
  2199.     hid: string;
  2200.    Begin
  2201.      findopcode := A_NONE;
  2202.      { first search for extended opcodes          }
  2203.      { now, in this case, we must use the suffix  }
  2204.      { to determine the size of the instruction   }
  2205.      for j:=0 to _count_asmspecialops do
  2206.      Begin
  2207.        if s = _specialops[j] then
  2208.        Begin
  2209.          findopcode := _specialopstokens[j];
  2210.          { set the size }
  2211.          case s[length(s)] of
  2212.          'B': instr.stropsize := S_B;
  2213.          'L': instr.stropsize := S_L;
  2214.          'W': instr.stropsize := S_W;
  2215.          end;
  2216.          exit;
  2217.        end;
  2218.      end;
  2219.      for i:=firstop to lastop do
  2220.      Begin
  2221.             if s=iasmops^[i] then
  2222.              begin
  2223.                findopcode := i;
  2224.                instr.stropsize := S_NO;
  2225.                exit;
  2226.              end;
  2227.      end;
  2228.      { not found yet ... }
  2229.      { search for all possible suffixes }
  2230.      for hs:=S_WL downto S_B do
  2231.         if copy(s,length(s)-length(att_opsize2str[hs])+1,
  2232.           length(att_opsize2str[hs]))=upper(att_opsize2str[hs]) then
  2233.         begin
  2234.            hid:=copy(s,1,length(s)-length(att_opsize2str[hs]));
  2235.            for i:=firstop to lastop do
  2236.               if (length(hid) > 0) and (hid=iasmops^[i]) then
  2237.               begin
  2238.                 findopcode := i;
  2239.                 instr.stropsize := hs;
  2240.                 exit;
  2241.               end;
  2242.         end;
  2243.   end;
  2244.  
  2245.  
  2246.    Function CheckPrefix(prefix: tasmop; opcode:tasmop): Boolean;
  2247.    { Checks if the prefix is valid with the following instruction }
  2248.    { return false if not, otherwise true                          }
  2249.    Begin
  2250.      CheckPrefix := TRUE;
  2251.      Case prefix of
  2252.        A_REP,A_REPNE,A_REPE: if not (opcode in [A_SCAS,A_INS,A_OUTS,A_MOVS,
  2253.                              A_CMPS,A_LODS,A_STOS]) then
  2254.                              Begin
  2255.                                CheckPrefix := FALSE;
  2256.                                exit;
  2257.                              end;
  2258.        A_LOCK: if not (opcode in [A_BT,A_BTS,A_BTR,A_BTC,A_XCHG,A_ADD,A_OR,
  2259.                         A_ADC,A_SBB,A_AND,A_SUB,A_XOR,A_NOT,A_NEG,A_INC,A_DEC]) then
  2260.                   Begin
  2261.                      CheckPrefix := FALSE;
  2262.                      Exit;
  2263.                   end;
  2264.        A_NONE: exit; { no prefix here }
  2265.  
  2266.      else
  2267.        CheckPrefix := FALSE;
  2268.      end; { end case }
  2269.    end;
  2270.  
  2271.  
  2272.   Procedure InitAsmRef(var instr: TInstruction);
  2273.   {*********************************************************************}
  2274.   {  Description: This routine first check if the instruction is of     }
  2275.   {  type OPR_NONE, or OPR_REFERENCE , if not it gives out an error.    }
  2276.   {  If the operandtype = OPR_NONE or <> OPR_REFERENCE then it sets up  }
  2277.   {  the operand type to OPR_REFERENCE, as well as setting up the ref   }
  2278.   {  to point to the default segment.                                   }
  2279.   {*********************************************************************}
  2280.    Begin
  2281.      With instr do
  2282.      Begin
  2283.         case operands[operandnum].operandtype of
  2284.           OPR_REFERENCE: exit;
  2285.           OPR_NONE: ;
  2286.         else
  2287.           Message(assem_e_invalid_operand_type);
  2288.         end;
  2289.         operands[operandnum].operandtype := OPR_REFERENCE;
  2290.         operands[operandnum].ref.segment := R_DEFAULT_SEG;
  2291.      end;
  2292.    end;
  2293.  
  2294.    Function CheckOverride(segreg: tregister; var instr: TInstruction): Boolean;
  2295.    { Check if the override is valid, and if so then }
  2296.    { update the instr variable accordingly.         }
  2297.    Begin
  2298.      CheckOverride := FALSE;
  2299.      if instr.getinstruction in [A_MOVS,A_XLAT,A_CMPS] then
  2300.      Begin
  2301.        CheckOverride := TRUE;
  2302.        Message(assem_e_segment_override_not_supported);
  2303.      end
  2304.    end;
  2305.  
  2306.  
  2307.  
  2308.  
  2309.   Function CalculateExpression(expression: string): longint;
  2310.   var
  2311.     expr: TExprParse;
  2312.   Begin
  2313.    expr.Init;
  2314.    CalculateExpression := expr.Evaluate(expression);
  2315.    expr.Done;
  2316.   end;
  2317.  
  2318.  
  2319.  
  2320.  
  2321.   Function BuildExpression: longint;
  2322.   {*********************************************************************}
  2323.   { FUNCTION BuildExpression: longint                                   }
  2324.   {  Description: This routine calculates a constant expression to      }
  2325.   {  a given value. The return value is the value calculated from       }
  2326.   {  the expression.                                                    }
  2327.   { The following tokens (not strings) are recognized:                  }
  2328.   {    (,),SHL,SHR,/,*,NOT,OR,XOR,AND,MOD,+/-,numbers,ID to constants.  }
  2329.   {*********************************************************************}
  2330.   { ENTRY: On entry the token should be any valid expression token.     }
  2331.   { EXIT:  On Exit the token points to either COMMA or SEPARATOR        }
  2332.   { ERROR RECOVERY: Tries to find COMMA or SEPARATOR token by consuming }
  2333.   {  invalid tokens.                                                    }
  2334.   {*********************************************************************}
  2335.   var expr: string;
  2336.       tempstr: string;
  2337.       l : longint;
  2338.       errorflag: boolean;
  2339.   Begin
  2340.     errorflag := FALSE;
  2341.     expr := '';
  2342.     tempstr := '';
  2343.     Repeat
  2344.       Case actasmtoken of
  2345.       AS_LPAREN: Begin
  2346.                   Consume(AS_LPAREN);
  2347.                   expr := expr + '(';
  2348.                 end;
  2349.       AS_RPAREN: Begin
  2350.                   Consume(AS_RPAREN);
  2351.                   expr := expr + ')';
  2352.                 end;
  2353.       AS_SHL:    Begin
  2354.                   Consume(AS_SHL);
  2355.                   expr := expr + '<';
  2356.                 end;
  2357.       AS_SHR:    Begin
  2358.                   Consume(AS_SHR);
  2359.                   expr := expr + '>';
  2360.                 end;
  2361.       AS_SLASH:  Begin
  2362.                   Consume(AS_SLASH);
  2363.                   expr := expr + '/';
  2364.                 end;
  2365.       AS_MOD:    Begin
  2366.                   Consume(AS_MOD);
  2367.                   expr := expr + '%';
  2368.                 end;
  2369.       AS_STAR:   Begin
  2370.                   Consume(AS_STAR);
  2371.                   expr := expr + '*';
  2372.                 end;
  2373.       AS_PLUS:   Begin
  2374.                   Consume(AS_PLUS);
  2375.                   expr := expr + '+';
  2376.                 end;
  2377.       AS_MINUS:  Begin
  2378.                   Consume(AS_MINUS);
  2379.                   expr := expr + '-';
  2380.                 end;
  2381.       AS_AND:    Begin
  2382.                   Consume(AS_AND);
  2383.                   expr := expr + '&';
  2384.                 end;
  2385.       AS_NOT:    Begin
  2386.                   Consume(AS_NOT);
  2387.                   expr := expr + '~';
  2388.                 end;
  2389.       AS_XOR:    Begin
  2390.                   Consume(AS_XOR);
  2391.                   expr := expr + '^';
  2392.                 end;
  2393.       AS_OR:     Begin
  2394.                   Consume(AS_OR);
  2395.                   expr := expr + '|';
  2396.                 end;
  2397.       AS_ID:    Begin
  2398.                   if NOT SearchIConstant(actasmpattern,l) then
  2399.                   Begin
  2400.                     Message1(assem_e_invalid_const_symbol,actasmpattern);
  2401.                     l := 0;
  2402.                   end;
  2403.                   str(l, tempstr);
  2404.                   expr := expr + tempstr;
  2405.                   Consume(AS_ID);
  2406.                 end;
  2407.       AS_INTNUM:  Begin
  2408.                    expr := expr + actasmpattern;
  2409.                    Consume(AS_INTNUM);
  2410.                  end;
  2411.       AS_BINNUM:  Begin
  2412.                       tempstr := BinaryToDec(actasmpattern);
  2413.                       if tempstr = '' then
  2414.                        Message(assem_f_error_converting_bin);
  2415.                       expr:=expr+tempstr;
  2416.                       Consume(AS_BINNUM);
  2417.                  end;
  2418.  
  2419.       AS_HEXNUM: Begin
  2420.                     tempstr := HexToDec(actasmpattern);
  2421.                     if tempstr = '' then
  2422.                      Message(assem_f_error_converting_hex);
  2423.                     expr:=expr+tempstr;
  2424.                     Consume(AS_HEXNUM);
  2425.                 end;
  2426.       AS_OCTALNUM: Begin
  2427.                     tempstr := OctalToDec(actasmpattern);
  2428.                     if tempstr = '' then
  2429.                      Message(assem_f_error_converting_octal);
  2430.                     expr:=expr+tempstr;
  2431.                     Consume(AS_OCTALNUM);
  2432.                   end;
  2433.       { go to next term }
  2434.       AS_COMMA: Begin
  2435.                   if not ErrorFlag then
  2436.                     BuildExpression := CalculateExpression(expr)
  2437.                   else
  2438.                     BuildExpression := 0;
  2439.                   Exit;
  2440.                end;
  2441.       { go to next symbol }
  2442.       AS_SEPARATOR: Begin
  2443.                       if not ErrorFlag then
  2444.                         BuildExpression := CalculateExpression(expr)
  2445.                       else
  2446.                         BuildExpression := 0;
  2447.                       Exit;
  2448.                    end;
  2449.       else
  2450.         Begin
  2451.           { only write error once. }
  2452.           if not errorflag then
  2453.            Message(assem_e_invalid_constant_expression);
  2454.           { consume tokens until we find COMMA or SEPARATOR }
  2455.           Consume(actasmtoken);
  2456.           errorflag := TRUE;
  2457.         End;
  2458.       end;
  2459.     Until false;
  2460.   end;
  2461.  
  2462.  
  2463.   Procedure BuildRealConstant(typ : tfloattype);
  2464.   {*********************************************************************}
  2465.   { PROCEDURE BuilRealConst                                             }
  2466.   {  Description: This routine calculates a constant expression to      }
  2467.   {  a given value. The return value is the value calculated from       }
  2468.   {  the expression.                                                    }
  2469.   { The following tokens (not strings) are recognized:                  }
  2470.   {    +/-,numbers and real numbers                                     }
  2471.   {*********************************************************************}
  2472.   { ENTRY: On entry the token should be any valid expression token.     }
  2473.   { EXIT:  On Exit the token points to either COMMA or SEPARATOR        }
  2474.   { ERROR RECOVERY: Tries to find COMMA or SEPARATOR token by consuming }
  2475.   {  invalid tokens.                                                    }
  2476.   {*********************************************************************}
  2477.   var expr: string;
  2478.       tempstr: string;
  2479.       r : extended;
  2480.       code : word;
  2481.       negativ : boolean;
  2482.       errorflag: boolean;
  2483.   Begin
  2484.     errorflag := FALSE;
  2485.     Repeat
  2486.     negativ:=false;
  2487.     expr := '';
  2488.     tempstr := '';
  2489.     if actasmtoken=AS_PLUS then Consume(AS_PLUS)
  2490.     else if actasmtoken=AS_MINUS then
  2491.       begin
  2492.          negativ:=true;
  2493.          consume(AS_MINUS);
  2494.       end;
  2495.     Case actasmtoken of
  2496.       AS_INTNUM:  Begin
  2497.                    expr := actasmpattern;
  2498.                    Consume(AS_INTNUM);
  2499.                  end;
  2500.       AS_REALNUM:  Begin
  2501.                    expr := actasmpattern;
  2502.                    { in ATT syntax you have 0d in front of the real }
  2503.                    { should this be forced ?  yes i think so, as to }
  2504.                    { conform to gas as much as possible.            }
  2505.                    if (expr[1]='0') and (upper(expr[2])='D') then
  2506.                      expr:=copy(expr,3,255);
  2507.                    Consume(AS_REALNUM);
  2508.                  end;
  2509.       AS_BINNUM:  Begin
  2510.                       { checking for real constants with this should use  }
  2511.                       { real DECODING otherwise the compiler will crash!  }
  2512.                       Message(assem_w_float_bin_ignored);
  2513.                       Consume(AS_BINNUM);
  2514.                  end;
  2515.  
  2516.       AS_HEXNUM: Begin
  2517.                       { checking for real constants with this should use  }
  2518.                       { real DECODING otherwise the compiler will crash!  }
  2519.                     Message(assem_w_float_hex_ignored);
  2520.                     Consume(AS_HEXNUM);
  2521.                 end;
  2522.       AS_OCTALNUM: Begin
  2523.                       { checking for real constants with this should use    }
  2524.                       { real DECODING otherwise the compiler will crash!    }
  2525.                       { xxxToDec using reals could be a solution, but the   }
  2526.                       { problem is that these will crash the m68k compiler  }
  2527.                       { when compiling -- because of lack of good fpu       }
  2528.                       { support.                                           }
  2529.                     Message(assem_w_float_octal_ignored);
  2530.                     Consume(AS_OCTALNUM);
  2531.                   end;
  2532.          else
  2533.            Begin
  2534.              { only write error once. }
  2535.              if not errorflag then
  2536.               Message(assem_e_invalid_real_const);
  2537.              { consume tokens until we find COMMA or SEPARATOR }
  2538.              Consume(actasmtoken);
  2539.              errorflag := TRUE;
  2540.            End;
  2541.  
  2542.          end;
  2543.       { go to next term }
  2544.       if (actasmtoken=AS_COMMA) or (actasmtoken=AS_SEPARATOR) then
  2545.         Begin
  2546.           if negativ then expr:='-'+expr;
  2547.           val(expr,r,code);
  2548.           if code<>0 then
  2549.             Begin
  2550.                r:=0;
  2551.                Message(assem_e_invalid_real_const);
  2552.                ConcatRealConstant(p,r,typ);
  2553.             End
  2554.           else
  2555.             Begin
  2556.               ConcatRealConstant(p,r,typ);
  2557.             End;
  2558.         end
  2559.       else
  2560.        Message(assem_e_invalid_real_const);
  2561.     Until actasmtoken=AS_SEPARATOR;
  2562.   end;
  2563.  
  2564.  
  2565.  
  2566.   Procedure BuildScaling(Var instr: TInstruction);
  2567.   {*********************************************************************}
  2568.   {  Takes care of parsing expression starting from the scaling value   }
  2569.   {  up to and including possible field specifiers.                     }
  2570.   { EXIT CONDITION:  On exit the routine should point to  AS_SEPARATOR  }
  2571.   { or AS_COMMA. On entry should point to the AS_COMMA token.           }
  2572.   {*********************************************************************}
  2573.   var str:string;
  2574.       l: longint;
  2575.       code: integer;
  2576.   Begin
  2577.      Consume(AS_COMMA);
  2578.      if (instr.operands[operandnum].ref.scalefactor <> 0)
  2579.      and (instr.operands[operandnum].ref.scalefactor <> 1) then
  2580.       Message(assem_f_internal_error_in_buildscale);
  2581.      case actasmtoken of
  2582.         AS_INTNUM: str := actasmpattern;
  2583.         AS_HEXNUM: str := HexToDec(actasmpattern);
  2584.         AS_BINNUM: str := BinaryToDec(actasmpattern);
  2585.         AS_OCTALNUM: str := OctalToDec(actasmpattern);
  2586.      else
  2587.         Message(assem_e_syntax_error);
  2588.      end;
  2589.      val(str, l, code);
  2590.      if code <> 0 then
  2591.        Message(assem_e_invalid_scaling_factor);
  2592.      if ((l = 2) or (l = 4) or (l = 8) or (l = 1)) and (code = 0) then
  2593.      begin
  2594.         instr.operands[operandnum].ref.scalefactor := l;
  2595.      end
  2596.      else
  2597.      Begin
  2598.         Message(assem_e_invalid_scaling_value);
  2599.         instr.operands[operandnum].ref.scalefactor := 0;
  2600.      end;
  2601.      if instr.operands[operandnum].ref.index = R_NO then
  2602.      Begin
  2603.         Message(assem_e_scaling_value_only_allowed_with_index);
  2604.         instr.operands[operandnum].ref.scalefactor := 0;
  2605.      end;
  2606.     { Consume the scaling number }
  2607.     Consume(actasmtoken);
  2608.     if actasmtoken = AS_RPAREN then
  2609.         Consume(AS_RPAREN)
  2610.     else
  2611.        Message(assem_e_invalid_scaling_value);
  2612.     { // .Field.Field ... or separator/comma // }
  2613.     if actasmtoken in [AS_COMMA,AS_SEPARATOR] then
  2614.     Begin
  2615.     end
  2616.     else
  2617.       Message(assem_e_syntax_error);
  2618.   end;
  2619.  
  2620.  
  2621.  
  2622.  
  2623.   Function BuildRefExpression: longint;
  2624.   {*********************************************************************}
  2625.   { FUNCTION BuildExpression: longint                                   }
  2626.   {  Description: This routine calculates a constant expression to      }
  2627.   {  a given value. The return value is the value calculated from       }
  2628.   {  the expression.                                                    }
  2629.   { The following tokens (not strings) are recognized:                  }
  2630.   {    SHL,SHR,/,*,NOT,OR,XOR,AND,MOD,+/-,numbers,ID to constants.      }
  2631.   {*********************************************************************}
  2632.   { ENTRY: On entry the token should be any valid expression token.     }
  2633.   { EXIT:  On Exit the token points to the LPAREN token.                }
  2634.   { ERROR RECOVERY: Tries to find COMMA or SEPARATOR token by consuming }
  2635.   {  invalid tokens.                                                    }
  2636.   {*********************************************************************}
  2637.   var tempstr: string;
  2638.       expr: string;
  2639.     l : longint;
  2640.     errorflag : boolean;
  2641.   Begin
  2642.     errorflag := FALSE;
  2643.     tempstr := '';
  2644.     expr := '';
  2645.     Repeat
  2646.       Case actasmtoken of
  2647.       AS_RPAREN: Begin
  2648.                    Message(assem_e_parenthesis_are_not_allowed);
  2649.                    Consume(AS_RPAREN);
  2650.                  end;
  2651.       AS_SHL:    Begin
  2652.                    Consume(AS_SHL);
  2653.                    expr := expr + '<';
  2654.                  end;
  2655.       AS_SHR:    Begin
  2656.                   Consume(AS_SHR);
  2657.                   expr := expr + '>';
  2658.                 end;
  2659.       AS_SLASH:  Begin
  2660.                   Consume(AS_SLASH);
  2661.                   expr := expr + '/';
  2662.                 end;
  2663.       AS_MOD:    Begin
  2664.                   Consume(AS_MOD);
  2665.                   expr := expr + '%';
  2666.                 end;
  2667.       AS_STAR:   Begin
  2668.                   Consume(AS_STAR);
  2669.                   expr := expr + '*';
  2670.                 end;
  2671.       AS_PLUS:   Begin
  2672.                   Consume(AS_PLUS);
  2673.                   expr := expr + '+';
  2674.                 end;
  2675.       AS_MINUS:  Begin
  2676.                   Consume(AS_MINUS);
  2677.                   expr := expr + '-';
  2678.                 end;
  2679.       AS_AND:    Begin
  2680.                   Consume(AS_AND);
  2681.                   expr := expr + '&';
  2682.                 end;
  2683.       AS_NOT:    Begin
  2684.                   Consume(AS_NOT);
  2685.                   expr := expr + '~';
  2686.                 end;
  2687.       AS_XOR:    Begin
  2688.                   Consume(AS_XOR);
  2689.                   expr := expr + '^';
  2690.                 end;
  2691.       AS_OR:     Begin
  2692.                   Consume(AS_OR);
  2693.                   expr := expr + '|';
  2694.                 end;
  2695.       { End of reference }
  2696.       AS_LPAREN: Begin
  2697.                      if not ErrorFlag then
  2698.                         BuildRefExpression := CalculateExpression(expr)
  2699.                      else
  2700.                         BuildRefExpression := 0;
  2701.                      { no longer in an expression }
  2702.                      exit;
  2703.                   end;
  2704.       AS_ID:
  2705.                 Begin
  2706.                   if NOT SearchIConstant(actasmpattern,l) then
  2707.                   Begin
  2708.                     Message1(assem_e_invalid_const_symbol,actasmpattern);
  2709.                     l := 0;
  2710.                   end;
  2711.                   str(l, tempstr);
  2712.                   expr := expr + tempstr;
  2713.                   Consume(AS_ID);
  2714.                 end;
  2715.       AS_INTNUM:  Begin
  2716.                    expr := expr + actasmpattern;
  2717.                    Consume(AS_INTNUM);
  2718.                  end;
  2719.       AS_BINNUM:  Begin
  2720.                       tempstr := BinaryToDec(actasmpattern);
  2721.                       if tempstr = '' then
  2722.                        Message(assem_f_error_converting_bin);
  2723.                       expr:=expr+tempstr;
  2724.                       Consume(AS_BINNUM);
  2725.                  end;
  2726.  
  2727.       AS_HEXNUM: Begin
  2728.                     tempstr := HexToDec(actasmpattern);
  2729.                     if tempstr = '' then
  2730.                      Message(assem_f_error_converting_hex);
  2731.                     expr:=expr+tempstr;
  2732.                     Consume(AS_HEXNUM);
  2733.                 end;
  2734.       AS_OCTALNUM: Begin
  2735.                     tempstr := OctalToDec(actasmpattern);
  2736.                     if tempstr = '' then
  2737.                      Message(assem_f_error_converting_octal);
  2738.                     expr:=expr+tempstr;
  2739.                     Consume(AS_OCTALNUM);
  2740.                   end;
  2741.       else
  2742.         Begin
  2743.           { write error only once. }
  2744.           if not errorflag then
  2745.            Message(assem_e_invalid_constant_expression);
  2746.           BuildRefExpression := 0;
  2747.           if actasmtoken in [AS_COMMA,AS_SEPARATOR] then exit;
  2748.           { consume tokens until we find COMMA or SEPARATOR }
  2749.           Consume(actasmtoken);
  2750.           errorflag := TRUE;
  2751.         end;
  2752.       end;
  2753.     Until false;
  2754.   end;
  2755.  
  2756.  
  2757.  
  2758.  
  2759.   Procedure BuildReference(var Instr: TInstruction);
  2760.   {*********************************************************************}
  2761.   { PROCEDURE BuildBracketExpression                                    }
  2762.   {  Description: This routine builds up an expression after a LPAREN   }
  2763.   {  token is encountered.                                              }
  2764.   {   On entry actasmtoken should be equal to AS_LPAREN                 }
  2765.   {*********************************************************************}
  2766.   { EXIT CONDITION:  On exit the routine should point to either the     }
  2767.   {       AS_COMMA or AS_SEPARATOR token.                               }
  2768.   {*********************************************************************}
  2769.   var
  2770.     l:longint;
  2771.     code: integer;
  2772.     str: string;
  2773.   Begin
  2774.      Consume(AS_LPAREN);
  2775.      initAsmRef(instr);
  2776.      Case actasmtoken of
  2777.         { // (reg ... // }
  2778.         AS_REGISTER: Begin
  2779.                         instr.operands[operandnum].ref.base :=
  2780.                            findregister(actasmpattern);
  2781.                         Consume(AS_REGISTER);
  2782.                         { can either be a register or a right parenthesis }
  2783.                          { // (reg)       // }
  2784.                          if actasmtoken=AS_RPAREN then  Begin
  2785.                                        Consume(AS_RPAREN);
  2786.                                        if not (actasmtoken in [AS_COMMA,
  2787.                                          AS_SEPARATOR]) then
  2788.                                        Begin
  2789.                                          Message(assem_e_invalid_reference);
  2790.                                          { error recovery ... }
  2791.                                          while actasmtoken <> AS_SEPARATOR do
  2792.                                            Consume(actasmtoken);
  2793.                                        end;
  2794.                                          exit;
  2795.                                      end;
  2796.                        { // (reg,reg .. // }
  2797.                        { we need a comman here !! }
  2798.                        { oops..                   }
  2799.                         Consume(AS_COMMA);
  2800.  
  2801.                         Case actasmtoken of
  2802.                          AS_REGISTER: Begin
  2803.                                         instr.operands[operandnum].ref.index :=
  2804.                                            findregister(actasmpattern);
  2805.                                         Consume(AS_REGISTER);
  2806.                                         { check for scaling ... }
  2807.                                         case actasmtoken of
  2808.                                          AS_RPAREN:
  2809.                                                Begin
  2810.                                                  Consume(AS_RPAREN);
  2811.                                                  if not (actasmtoken in [AS_COMMA,
  2812.                                                     AS_SEPARATOR]) then
  2813.                                                   Begin
  2814.                                                     { error recovery ... }
  2815.                                                     Message(assem_e_invalid_reference);
  2816.                                                     while actasmtoken <> AS_SEPARATOR do
  2817.                                                     Consume(actasmtoken);
  2818.                                                   end;
  2819.                                                    exit;
  2820.                                                end;
  2821.                                          AS_COMMA:
  2822.                                                Begin
  2823.                                                  BuildScaling(instr);
  2824.                                                end;
  2825.                                          else
  2826.                                           Begin
  2827.                                              Message(assem_e_invalid_reference_syntax);
  2828.                                              while (actasmtoken <> AS_SEPARATOR) do
  2829.                                              Consume(actasmtoken);
  2830.                                           end;
  2831.                                          end; { end case }
  2832.                                         end;
  2833.                          else
  2834.                           Begin
  2835.                             Message(assem_e_invalid_reference_syntax);
  2836.                             while (actasmtoken <> AS_SEPARATOR) do
  2837.                                 Consume(actasmtoken);
  2838.                           end;
  2839.                          end; {end case }
  2840.                      end;
  2841.         { // (, ...   // }
  2842.         AS_COMMA:  { can either be scaling, or index }
  2843.                    Begin
  2844.                      Consume(AS_COMMA);
  2845.                      case actasmtoken of
  2846.                        AS_REGISTER: Begin
  2847.                                       instr.operands[operandnum].ref.index :=
  2848.                                          findregister(actasmpattern);
  2849.                                       Consume(AS_REGISTER);
  2850.                                         { check for scaling ... }
  2851.                                         case actasmtoken of
  2852.                                          AS_RPAREN:
  2853.                                                Begin
  2854.                                                  Consume(AS_RPAREN);
  2855.                                                  if not (actasmtoken in [AS_COMMA,
  2856.                                                     AS_SEPARATOR]) then
  2857.                                                   Begin
  2858.                                                     { error recovery ... }
  2859.                                                     Message(assem_e_invalid_reference);
  2860.                                                     while actasmtoken <> AS_SEPARATOR do
  2861.                                                     Consume(actasmtoken);
  2862.                                                   end;
  2863.                                                    exit;
  2864.                                                end;
  2865.                                          AS_COMMA:
  2866.                                                Begin
  2867.                                                  BuildScaling(instr);
  2868.                                                end;
  2869.                                          else
  2870.                                           Begin
  2871.                                              Message(assem_e_invalid_reference_syntax);
  2872.                                              while (actasmtoken <> AS_SEPARATOR) do
  2873.                                              Consume(actasmtoken);
  2874.                                           end;
  2875.                                          end; {end case }
  2876.                                     end;
  2877.                        AS_HEXNUM,AS_INTNUM,   { we have to process the scaling }
  2878.                        AS_BINNUM,AS_OCTALNUM: { directly here...               }
  2879.                                               Begin
  2880.                                                   case actasmtoken of
  2881.                                                     AS_INTNUM: str :=
  2882.                                                        actasmpattern;
  2883.                                                     AS_HEXNUM: str :=
  2884.                                                        HexToDec(actasmpattern);
  2885.                                                     AS_BINNUM: str :=
  2886.                                                        BinaryToDec(actasmpattern);
  2887.                                                     AS_OCTALNUM: str :=
  2888.                                                        OctalToDec(actasmpattern);
  2889.                                                   else
  2890.                                                     Message(assem_e_syntax_error);
  2891.                                                   end; { end case }
  2892.                                                   val(str, l, code);
  2893.                                                   if code <> 0 then
  2894.                                                      Message(assem_e_invalid_scaling_factor);
  2895.                                                   if ((l = 2) or (l = 4) or (l = 8) or (l = 1)) and (code = 0) then
  2896.                                                   begin
  2897.                                                     instr.operands[operandnum].
  2898.                                                        ref.scalefactor := l;
  2899.                                                   end
  2900.                                                   else
  2901.                                                   Begin
  2902.                                                     Message(assem_e_invalid_scaling_value);
  2903.                                                     instr.operands[operandnum].
  2904.                                                        ref.scalefactor := 0;
  2905.                                                   end;
  2906.                                                   Consume(actasmtoken);
  2907.                                                   if actasmtoken <> AS_RPAREN then
  2908.                                                   Begin
  2909.                                                     Message(assem_e_invalid_scaling_value);
  2910.                                                     while actasmtoken <> AS_SEPARATOR do
  2911.                                                       Consume(actasmtoken);
  2912.                                                   end
  2913.                                                   else
  2914.                                                   Begin
  2915.                                                     Consume(AS_RPAREN);
  2916.                                                     if not (actasmtoken in [AS_COMMA,
  2917.                                                        AS_SEPARATOR]) then
  2918.                                                      Begin
  2919.                                                       { error recovery ... }
  2920.                                                       Message(assem_e_invalid_reference);
  2921.                                                       while actasmtoken <> AS_SEPARATOR do
  2922.                                                         Consume(actasmtoken);
  2923.                                                      end;
  2924.                                                     exit;
  2925.                                                   end;
  2926.                                               end;
  2927.                      else
  2928.                        Begin
  2929.                           Message(assem_e_invalid_reference_syntax);
  2930.                           while (actasmtoken <> AS_SEPARATOR) do
  2931.                           Consume(actasmtoken);
  2932.                        end;
  2933.                      end; { end case }
  2934.                    end;
  2935.  
  2936.      else
  2937.        Begin
  2938.          Message(assem_e_invalid_reference_syntax);
  2939.          while (actasmtoken <> AS_SEPARATOR) do
  2940.            Consume(actasmtoken);
  2941.        end;
  2942.      end; { end case }
  2943.   end;
  2944.  
  2945.  
  2946.  
  2947.   Procedure BuildOperand(var instr: TInstruction);
  2948.   {*********************************************************************}
  2949.   { EXIT CONDITION:  On exit the routine should point to either the     }
  2950.   {       AS_COMMA or AS_SEPARATOR token.                               }
  2951.   {*********************************************************************}
  2952.   var
  2953.     tempstr: string;
  2954.     expr: string;
  2955.     lab: Pasmlabel;
  2956.     hl: plabel;
  2957.   Begin
  2958.    tempstr := '';
  2959.    expr := '';
  2960.    case actasmtoken of
  2961.    { // Memory reference //  }
  2962.      AS_LPAREN:
  2963.                Begin
  2964.                   initAsmRef(instr);
  2965.                   BuildReference(instr);
  2966.                end;
  2967.    { // Constant expression //  }
  2968.      AS_DOLLAR:  Begin
  2969.                       Consume(AS_DOLLAR);
  2970.                       if not (instr.operands[operandnum].operandtype in [OPR_NONE,OPR_CONSTANT]) then
  2971.                        Message(assem_e_invalid_operand_type);
  2972.                       { identifiers are handled by BuildExpression }
  2973.                       instr.operands[operandnum].operandtype := OPR_CONSTANT;
  2974.                       instr.operands[operandnum].val :=BuildExpression;
  2975.                  end;
  2976.    { // Constant memory offset .              // }
  2977.    { // This must absolutely be followed by ( // }
  2978.      AS_HEXNUM,AS_INTNUM,AS_MINUS,
  2979.      AS_BINNUM,AS_OCTALNUM,AS_PLUS:
  2980.                    Begin
  2981.                       InitAsmRef(instr);
  2982.                       instr.operands[operandnum].ref.offset:=BuildRefExpression;
  2983.                       BuildReference(instr);
  2984.                    end;
  2985.    { // A constant expression, or a Variable ref. // }
  2986.      AS_ID:  Begin
  2987.               { // Local label.                      // }
  2988.               if (actasmpattern[1] ='.') and (actasmpattern[2] = 'L') then
  2989.               Begin
  2990.                   Begin
  2991.                     delete(actasmpattern,1,1);
  2992.                     delete(actasmpattern,1,1);
  2993.                     if actasmpattern = '' then
  2994.                      Message(assem_e_null_label_ref_not_allowed);
  2995.                     lab := labellist.search(actasmpattern);
  2996.                     { check if the label is already defined   }
  2997.                     { if so, we then check if the plabel is   }
  2998.                     { non-nil, if so we add it to instruction }
  2999.                     if assigned(lab) then
  3000.                      Begin
  3001.                      if assigned(lab^.lab) then
  3002.                        Begin
  3003.                          instr.operands[operandnum].operandtype := OPR_LABINSTR;
  3004.                          instr.operands[operandnum].hl := lab^.lab;
  3005.                          instr.labeled := TRUE;
  3006.                        end;
  3007.                      end
  3008.                     else
  3009.                     { the label does not exist, create it }
  3010.                     { emit the opcode, but set that the   }
  3011.                     { label has not been emitted          }
  3012.                      Begin
  3013.                         getlabel(hl);
  3014.                         labellist.insert(actasmpattern,hl,FALSE);
  3015.                         instr.operands[operandnum].operandtype := OPR_LABINSTR;
  3016.                         instr.operands[operandnum].hl := hl;
  3017.                         instr.labeled := TRUE;
  3018.                      end;
  3019.                   end;
  3020.                 Consume(AS_ID);
  3021.                 if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
  3022.                 Begin
  3023.                   Message(assem_e_syntax_error);
  3024.                 end;
  3025.               end
  3026.               { probably a variable or normal expression }
  3027.               { or a procedure (such as in CALL ID)      }
  3028.               else
  3029.                Begin
  3030.                  { check if this is a label, if so then }
  3031.                  { emit it as a label.                  }
  3032.                  if SearchLabel(actasmpattern,hl) then
  3033.                    Begin
  3034.                      instr.operands[operandnum].operandtype := OPR_LABINSTR;
  3035.                      instr.operands[operandnum].hl := hl;
  3036.                      instr.labeled := TRUE;
  3037.                      Consume(AS_ID);
  3038.                      if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
  3039.                        Message(assem_e_syntax_error);
  3040.                    end
  3041.                  else
  3042.                  { is it a normal variable ? }
  3043.                    Begin
  3044.                      initAsmRef(instr);
  3045.                      if not CreateVarInstr(instr,actasmpattern,operandnum) then
  3046.                        Begin
  3047.                          { look for special symbols ... }
  3048.                          if actasmpattern = '__RESULT' then
  3049.                              SetUpResult(instr,operandnum)
  3050.                          else
  3051.                          if actasmpattern = '__SELF' then
  3052.                          Begin
  3053.                            if assigned(procinfo._class) then
  3054.                              Begin
  3055.                                instr.operands[operandnum].operandtype := OPR_REFERENCE;
  3056.                                instr.operands[operandnum].ref.offset :=
  3057.                                  procinfo.ESI_offset;
  3058.                                instr.operands[operandnum].ref.base :=
  3059.                                  procinfo.framepointer;
  3060.                              end
  3061.                            else
  3062.                              Message(assem_e_cannot_use___SELF_outside_methode);
  3063.                          end
  3064.                          else
  3065.                          if actasmpattern = '__OLDEBP' then
  3066.                          Begin
  3067.                            if lexlevel>2 then
  3068.                              Begin
  3069.                                instr.operands[operandnum].operandtype := OPR_REFERENCE;
  3070.                                instr.operands[operandnum].ref.offset :=
  3071.                                  procinfo.framepointer_offset;
  3072.                                instr.operands[operandnum].ref.base :=
  3073.                                  procinfo.framepointer;
  3074.                              end
  3075.                            else
  3076.                              Message(assem_e_cannot_use___OLDEBP_outside_nested_procedure);
  3077.                          end { endif actasmpattern = '__OLDEBP' }
  3078.                          else
  3079.                          { check for direct symbolic names   }
  3080.                          { only if compiling the system unit }
  3081.                          if (cs_compilesystem in aktswitches) then
  3082.                          begin
  3083.                            if not SearchDirectVar(instr,actasmpattern,operandnum) then
  3084.                            Begin
  3085.                             { not found, finally ... add it anyways ... }
  3086.                             Message1(assem_w_id_supposed_external,actasmpattern);
  3087.                             instr.operands[operandnum].ref.symbol := newpasstr(actasmpattern);
  3088.                            end;
  3089.                          end
  3090.                          else
  3091.                           Message1(assem_e_unknown_id,actasmpattern);
  3092.                       end;
  3093.                      expr := actasmpattern;
  3094.                      Consume(AS_ID);
  3095.                        case actasmtoken of
  3096.                            AS_LPAREN: { indexing }
  3097.                                         BuildReference(instr);
  3098.                            AS_SEPARATOR,AS_COMMA: ;
  3099.                        else
  3100.                            Message(assem_e_syntax_error);
  3101.                        end; { end case }
  3102.                    end; { end if }
  3103.                end; { end if }
  3104.              end; { end this case }
  3105.    { // Register, a variable reference or a constant reference // }
  3106.      AS_REGISTER: Begin
  3107.                    { save the type of register used. }
  3108.                    tempstr := actasmpattern;
  3109.                    Consume(AS_REGISTER);
  3110.                    if actasmtoken = AS_COLON then
  3111.                    Begin
  3112.                       Consume(AS_COLON);
  3113.                       initAsmRef(instr);
  3114.                       instr.operands[operandnum].ref.segment := findsegment(tempstr);
  3115.                       { here we can have either an identifier }
  3116.                       { or a constant, where either can be    }
  3117.                       { followed by a parenthesis...          }
  3118.                       { // Constant memory offset .              // }
  3119.                       { // This must absolutely be followed by ( // }
  3120.                       case actasmtoken of
  3121.                         AS_HEXNUM,AS_INTNUM,AS_MINUS,
  3122.                         AS_BINNUM,AS_OCTALNUM,AS_PLUS
  3123.                         :  Begin
  3124.                                        instr.operands[operandnum].
  3125.                                        ref.offset:=BuildRefExpression;
  3126.                                        BuildReference(instr);
  3127.                                       end;
  3128.                         AS_LPAREN: BuildReference(instr);
  3129.                         { only a variable is allowed ... }
  3130.                         AS_ID: Begin
  3131.                                  { is it a normal variable ? }
  3132.                                  if not CreateVarInstr(instr,actasmpattern,operandnum)
  3133.                                  then
  3134.                                  begin
  3135.                                   {  check for direct symbolic names   }
  3136.                                    { only if compiling the system unit }
  3137.                                    if (cs_compilesystem in aktswitches) then
  3138.                                    begin
  3139.                                      if not SearchDirectVar(instr,actasmpattern,operandnum) then
  3140.                                         Message(assem_e_invalid_seg_override);
  3141.                                    end
  3142.                                    else
  3143.                                         Message(assem_e_invalid_seg_override);
  3144.                                  end;
  3145.                                  Consume(actasmtoken);
  3146.                                  case actasmtoken of
  3147.                                    AS_SEPARATOR,AS_COMMA: ;
  3148.                                    AS_LPAREN: BuildReference(instr);
  3149.                                  else
  3150.                                   Begin
  3151.                                    Message(assem_e_invalid_seg_override);
  3152.                                    Consume(actasmtoken);
  3153.                                   end;
  3154.                                  end; {end case }
  3155.                                end;
  3156.                       else
  3157.                           Begin
  3158.                             Message(assem_e_invalid_seg_override);
  3159.                             Consume(actasmtoken);
  3160.                           end;
  3161.                       end; { end case }
  3162.                    end
  3163.                    { // Simple register // }
  3164.                    else if (actasmtoken = AS_SEPARATOR) or (actasmtoken = AS_COMMA) then
  3165.                    Begin
  3166.                         if not (instr.operands[operandnum].operandtype in [OPR_NONE,OPR_REGISTER]) then
  3167.                          Message(assem_e_invalid_operand_type);
  3168.                         instr.operands[operandnum].operandtype := OPR_REGISTER;
  3169.                         instr.operands[operandnum].reg := findregister(tempstr);
  3170.                    end
  3171.                    else
  3172.                     Message1(assem_e_syn_register,tempstr);
  3173.                  end;
  3174.      AS_SEPARATOR, AS_COMMA: ;
  3175.     else
  3176.      Begin
  3177.       Message(assem_e_syn_opcode_operand);
  3178.       Consume(actasmtoken);
  3179.      end;
  3180.   end; { end case }
  3181.  end;
  3182.  
  3183.  
  3184.  
  3185.   Procedure BuildConstant(maxvalue: longint);
  3186.   {*********************************************************************}
  3187.   { PROCEDURE BuildConstant                                             }
  3188.   {  Description: This routine takes care of parsing a DB,DD,or DW      }
  3189.   {  line and adding those to the assembler node. Expressions, range-   }
  3190.   {  checking are fullly taken care of.                                 }
  3191.   {   maxvalue: $ff -> indicates that this is a DB node.                }
  3192.   {             $ffff -> indicates that this is a DW node.              }
  3193.   {             $ffffffff -> indicates that this is a DD node.          }
  3194.   {*********************************************************************}
  3195.   { EXIT CONDITION:  On exit the routine should point to AS_SEPARATOR.  }
  3196.   {*********************************************************************}
  3197.   var
  3198.    strlength: byte;
  3199.    expr: string;
  3200.    value : longint;
  3201.   Begin
  3202.       Repeat
  3203.         Case actasmtoken of
  3204.           AS_STRING: Begin
  3205.                       if maxvalue = $ff then
  3206.                          strlength := 1
  3207.                       else
  3208.                          Message(assem_e_string_not_allowed_as_const);
  3209.                       expr := actasmpattern;
  3210.                       if length(expr) > 1 then
  3211.                        Message(assem_e_string_not_allowed_as_const);
  3212.                       Consume(AS_STRING);
  3213.                       Case actasmtoken of
  3214.                        AS_COMMA: Consume(AS_COMMA);
  3215.                        AS_SEPARATOR: ;
  3216.                       else
  3217.                          Message(assem_e_invalid_string_expression);
  3218.                       end; { end case }
  3219.                       ConcatString(p,expr);
  3220.                     end;
  3221.           AS_INTNUM,AS_BINNUM,
  3222.           AS_OCTALNUM,AS_HEXNUM:
  3223.                     Begin
  3224.                       value:=BuildExpression;
  3225.                       ConcatConstant(p,value,maxvalue);
  3226.                     end;
  3227.           AS_ID:
  3228.                      Begin
  3229.                       value:=BuildExpression;
  3230.                       if value > maxvalue then
  3231.                       Begin
  3232.                          Message(assem_e_expression_out_of_bounds);
  3233.                          { assuming a value of maxvalue }
  3234.                          value := maxvalue;
  3235.                       end;
  3236.                       ConcatConstant(p,value,maxvalue);
  3237.                   end;
  3238.           { These terms can start an assembler expression }
  3239.           AS_PLUS,AS_MINUS,AS_LPAREN,AS_NOT: Begin
  3240.                                           value := BuildExpression;
  3241.                                           ConcatConstant(p,value,maxvalue);
  3242.                                          end;
  3243.           AS_COMMA:  BEGIN
  3244.                        Consume(AS_COMMA);
  3245.                      END;
  3246.           AS_SEPARATOR: ;
  3247.  
  3248.         else
  3249.          Begin
  3250.            Message(assem_f_internal_error_in_buildconstant);
  3251.          end;
  3252.     end; { end case }
  3253.    Until actasmtoken = AS_SEPARATOR;
  3254.   end;
  3255.  
  3256.  
  3257.   Procedure BuildStringConstant(asciiz: boolean);
  3258.   {*********************************************************************}
  3259.   { PROCEDURE BuildStringConstant                                       }
  3260.   {  Description: Takes care of a ASCII, or ASCIIZ directive.           }
  3261.   {   asciiz: boolean -> if true then string will be null terminated.   }
  3262.   {*********************************************************************}
  3263.   { EXIT CONDITION:  On exit the routine should point to AS_SEPARATOR.  }
  3264.   { On ENTRY: Token should point to AS_STRING                           }
  3265.   {*********************************************************************}
  3266.   var
  3267.    expr: string;
  3268.    errorflag : boolean;
  3269.   Begin
  3270.       errorflag := FALSE;
  3271.       Repeat
  3272.         Case actasmtoken of
  3273.           AS_STRING: Begin
  3274.                       expr:=actasmpattern;
  3275.                       if asciiz then
  3276.                        expr:=expr+#0;
  3277.                       ConcatPasString(p,expr);
  3278.                       Consume(AS_STRING);
  3279.                     end;
  3280.           AS_COMMA:  BEGIN
  3281.                        Consume(AS_COMMA);
  3282.                      END;
  3283.           AS_SEPARATOR: ;
  3284.         else
  3285.          Begin
  3286.           Consume(actasmtoken);
  3287.           if not errorflag then
  3288.            Message(assem_e_invalid_string_expression);
  3289.           errorflag := TRUE;
  3290.          end;
  3291.     end; { end case }
  3292.    Until actasmtoken = AS_SEPARATOR;
  3293.   end;
  3294.  
  3295.  
  3296.  
  3297.  
  3298.   Procedure BuildOpCode;
  3299.   {*********************************************************************}
  3300.   { PROCEDURE BuildOpcode;                                              }
  3301.   {  Description: Parses the intel opcode and operands, and writes it   }
  3302.   {  in the TInstruction object.                                        }
  3303.   {*********************************************************************}
  3304.   { EXIT CONDITION:  On exit the routine should point to AS_SEPARATOR.  }
  3305.   { On ENTRY: Token should point to AS_OPCODE                           }
  3306.   {*********************************************************************}
  3307.   var asmtok: tasmop;
  3308.       op: tasmop;
  3309.       expr: string;
  3310.       segreg: tregister;
  3311.   Begin
  3312.     expr := '';
  3313.     asmtok := A_NONE; { assmume no prefix          }
  3314.     segreg := R_NO;   { assume no segment override }
  3315.  
  3316.     { //  prefix seg opcode               // }
  3317.     { //  prefix opcode                   // }
  3318.     if findprefix(actasmpattern,asmtok) then
  3319.     Begin
  3320.      { standard opcode prefix }
  3321.      if asmtok <> A_NONE then
  3322.        instr.addprefix(asmtok);
  3323.      Consume(AS_OPCODE);
  3324.     end;
  3325.     { //  opcode                          // }
  3326.     { allow for newline as in gas styled syntax }
  3327.     { under DOS you get two AS_SEPARATOR !! }
  3328.     while actasmtoken=AS_SEPARATOR do
  3329.       Consume(AS_SEPARATOR);
  3330.     if (actasmtoken <> AS_OPCODE) then
  3331.     Begin
  3332.       Message(assem_e_invalid_or_missing_opcode);
  3333.       { error recovery }
  3334.       While not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
  3335.          Consume(actasmtoken);
  3336.       exit;
  3337.     end
  3338.     else
  3339.     Begin
  3340.       op := findopcode(actasmpattern);
  3341.       instr.addinstr(op);
  3342.       { // Valid combination of prefix and instruction ? // }
  3343.       if (asmtok <> A_NONE) and (NOT CheckPrefix(asmtok,op)) then
  3344.         Message1(assem_e_invalid_prefix_and_opcode,actasmpattern);
  3345.       Consume(AS_OPCODE);
  3346.       { // Zero operand opcode ? // }
  3347.       if actasmtoken = AS_SEPARATOR then
  3348.         exit
  3349.       else
  3350.        operandnum := 1;
  3351.     end;
  3352.  
  3353.     While actasmtoken <> AS_SEPARATOR do
  3354.     Begin
  3355.        case actasmtoken of
  3356.          { //  Operand delimiter // }
  3357.          AS_COMMA: Begin
  3358.                   if operandnum > MaxOperands then
  3359.                     Message(assem_e_too_many_operands)
  3360.                   else
  3361.                     Inc(operandnum);
  3362.                   Consume(AS_COMMA);
  3363.                 end;
  3364.          { // End of asm operands for this opcode // }
  3365.          AS_SEPARATOR: ;
  3366.        else
  3367.          BuildOperand(instr);
  3368.      end; { end case }
  3369.     end; { end while }
  3370.   end;
  3371.  
  3372.  
  3373.  
  3374.  
  3375.   Function Assemble: Ptree;
  3376.   {*********************************************************************}
  3377.   { PROCEDURE Assemble;                                                 }
  3378.   {  Description: Parses the att assembler syntax, parsing is done      }
  3379.   {  according to GAs rules.                                            }
  3380.   {*********************************************************************}
  3381.   Var
  3382.    hl: plabel;
  3383.    labelptr,nextlabel : pasmlabel;
  3384.    commname : string;
  3385.    store_p : paasmoutput;
  3386.  
  3387.   Begin
  3388.     Message(assem_d_start_att);
  3389.     firsttoken := TRUE;
  3390.     operandnum := 0;
  3391.     { sets up all opcode and register tables in uppercase }
  3392.     if not _asmsorted then
  3393.     Begin
  3394.       SetupTables;
  3395.       _asmsorted := TRUE;
  3396.     end;
  3397.     p:=new(paasmoutput,init);
  3398.     { save pointer code section }
  3399.     store_p:=p;
  3400.     { setup label linked list }
  3401.     labellist.init;
  3402.     c:=asmgetchar;
  3403.     actasmtoken:=gettoken;
  3404.     while actasmtoken<>AS_END do
  3405.     Begin
  3406.       case actasmtoken of
  3407.         AS_LLABEL: Begin
  3408.                     labelptr := labellist.search(actasmpattern);
  3409.                     if not assigned(labelptr) then
  3410.                     Begin
  3411.                         getlabel(hl);
  3412.                         labellist.insert(actasmpattern,hl,TRUE);
  3413.                         ConcatLabel(p,A_LABEL,hl);
  3414.                     end
  3415.                     else
  3416.                     { the label has already been inserted into the  }
  3417.                     { label list, either as an instruction label (in}
  3418.                     { this case it has not been emitted), or as a   }
  3419.                     { duplicate local symbol (in this case it has   }
  3420.                     { already been emitted).                        }
  3421.                     Begin
  3422.                        if labelptr^.emitted then
  3423.                         Message1(assem_e_dup_local_sym,'.L'+labelptr^.name^)
  3424.                        else
  3425.                         Begin
  3426.                           if assigned(labelptr^.lab) then
  3427.                             ConcatLabel(p,A_LABEL,labelptr^.lab);
  3428.                           labelptr^.emitted := TRUE;
  3429.                         end;
  3430.                     end;
  3431.                     Consume(AS_LLABEL);
  3432.                   end;
  3433.         AS_LABEL: Begin
  3434.                      { when looking for Pascal labels, these must }
  3435.                      { be in uppercase.                           }
  3436.                      if SearchLabel(upper(actasmpattern),hl) then
  3437.                        ConcatLabel(p,A_LABEL, hl)
  3438.                      else
  3439.                      Begin
  3440.                        if (cs_compilesystem in aktswitches) then
  3441.                        begin
  3442.                           Message1(assem_e_unknown_label_identifer,actasmpattern);
  3443.                           { once again we don't know what it represents }
  3444.                           { so we simply concatenate it                 }
  3445.                           ConcatLocal(p,actasmpattern);
  3446.                        end
  3447.                        else
  3448.                         Message1(assem_e_unknown_label_identifer,actasmpattern);
  3449.                      end;
  3450.                      Consume(AS_LABEL);
  3451.                  end;
  3452.         AS_DW:   Begin
  3453.                    Consume(AS_DW);
  3454.                    BuildConstant($ffff);
  3455.                  end;
  3456.         AS_DATA: Begin
  3457.                  { -- this should only be allowed for system development -- }
  3458.                  {    i think this should be fixed in the dos unit, and     }
  3459.                  {    not here.                                             }
  3460.                    if (cs_compilesystem in aktswitches) then
  3461.                        p:=datasegment
  3462.                    else
  3463.                        Message(assem_e_switching_sections_not_allowed);
  3464.                    Consume(AS_DATA);
  3465.                  end;
  3466.         AS_TEXT: Begin
  3467.                  { -- this should only be allowed for system development -- }
  3468.                  {    i think this should be fixed in the dos unit, and     }
  3469.                  {    not here.                                             }
  3470.                    if (cs_compilesystem in aktswitches) then
  3471.                         p:=store_p
  3472.                    else
  3473.                        Message(assem_e_switching_sections_not_allowed);
  3474.                    Consume(AS_TEXT);
  3475.                  end;
  3476.         AS_DB:   Begin
  3477.                   Consume(AS_DB);
  3478.                   BuildConstant($ff);
  3479.                 end;
  3480.         AS_DD:   Begin
  3481.                  Consume(AS_DD);
  3482.                  BuildConstant($ffffffff);
  3483.                 end;
  3484.         AS_DQ:  Begin
  3485.                  Consume(AS_DQ);
  3486.                  BuildRealConstant(s64bit);
  3487.                 end;
  3488.         AS_SINGLE:   Begin
  3489.                  Consume(AS_SINGLE);
  3490.                  BuildRealConstant(s32real);
  3491.                 end;
  3492.         AS_DOUBLE:   Begin
  3493.                  Consume(AS_DOUBLE);
  3494.                  BuildRealConstant(s64real);
  3495.                 end;
  3496.         AS_EXTENDED:   Begin
  3497.                  Consume(AS_EXTENDED);
  3498.                  BuildRealConstant(s80real);
  3499.                 end;
  3500.         AS_GLOBAL:
  3501.                   Begin
  3502.                    { normal units should not be able to declare }
  3503.                    { direct label names like this... anyhow     }
  3504.                    { procedural calls in asm blocks are         }
  3505.                    { supposedely replaced automatically         }
  3506.                    if (cs_compilesystem in aktswitches) then
  3507.                    begin
  3508.                      Consume(AS_GLOBAL);
  3509.                       if actasmtoken <> AS_ID then
  3510.                         Message(assem_e_invalid_global_def)
  3511.                       else
  3512.                         ConcatPublic(p,actasmpattern);
  3513.                       Consume(actasmtoken);
  3514.                       if actasmtoken <> AS_SEPARATOR then
  3515.                       Begin
  3516.                         Message(assem_e_line_separator_expected);
  3517.                         while actasmtoken <> AS_SEPARATOR do
  3518.                          Consume(actasmtoken);
  3519.                       end;
  3520.                    end
  3521.                    else
  3522.                    begin
  3523.                      Message(assem_w_globl_not_supported);
  3524.                      while actasmtoken <> AS_SEPARATOR do
  3525.                        Consume(actasmtoken);
  3526.                    end;
  3527.                   end;
  3528.         AS_ALIGN: Begin
  3529.                     Message(assem_w_align_not_supported);
  3530.                     while actasmtoken <> AS_SEPARATOR do
  3531.                      Consume(actasmtoken);
  3532.                   end;
  3533.         AS_ASCIIZ: Begin
  3534.                      Consume(AS_ASCIIZ);
  3535.                      BuildStringConstant(TRUE);
  3536.                    end;
  3537.         AS_ASCII: Begin
  3538.                     Consume(AS_ASCII);
  3539.                     BuildStringConstant(FALSE);
  3540.                   end;
  3541.         AS_LCOMM: Begin
  3542.                  { -- this should only be allowed for system development -- }
  3543.                  { -- otherwise may mess up future enhancements we might -- }
  3544.                  { -- add.                                               -- }
  3545.                    if (cs_compilesystem in aktswitches) then
  3546.                    begin
  3547.                      Consume(AS_LCOMM);
  3548.                       if actasmtoken <> AS_ID then
  3549.                         begin
  3550.                            Message(assem_e_invalid_lcomm_def);
  3551.                            { error recovery }
  3552.                            while actasmtoken <> AS_SEPARATOR do
  3553.                             Consume(actasmtoken);
  3554.                         end
  3555.                       else
  3556.                         begin
  3557.                            commname:=actasmpattern;
  3558.                            Consume(AS_COMMA);
  3559.                            ConcatLocalBss(actasmpattern,BuildExpression);
  3560.                            if actasmtoken <> AS_SEPARATOR then
  3561.                              Begin
  3562.                                 Message(assem_e_line_separator_expected);
  3563.                                 while actasmtoken <> AS_SEPARATOR do
  3564.                                   Consume(actasmtoken);
  3565.                              end;
  3566.                         end;
  3567.                    end
  3568.                    else
  3569.                    begin
  3570.                         Message(assem_w_lcomm_not_supported);
  3571.                         while actasmtoken <> AS_SEPARATOR do
  3572.                           Consume(actasmtoken);
  3573.                    end;
  3574.                   end;
  3575.         AS_COMM: Begin
  3576.                  { -- this should only be allowed for system development -- }
  3577.                  { -- otherwise may mess up future enhancements we might -- }
  3578.                  { -- add.                                               -- }
  3579.                    if (cs_compilesystem in aktswitches) then
  3580.                    begin
  3581.                      Consume(AS_LCOMM);
  3582.                       if actasmtoken <> AS_ID then
  3583.                         begin
  3584.                            Message(assem_e_invalid_comm_def);
  3585.                            { error recovery }
  3586.                            while actasmtoken <> AS_SEPARATOR do
  3587.                             Consume(actasmtoken);
  3588.                         end
  3589.                       else
  3590.                         begin
  3591.                            commname:=actasmpattern;
  3592.                            Consume(AS_COMMA);
  3593.                            ConcatGlobalBss(actasmpattern,BuildExpression);
  3594.                            if actasmtoken <> AS_SEPARATOR then
  3595.                            Begin
  3596.                              Message(assem_e_line_separator_expected);
  3597.                              while actasmtoken <> AS_SEPARATOR do
  3598.                               Consume(actasmtoken);
  3599.                            end;
  3600.                         end;
  3601.                    end
  3602.                    else
  3603.                    begin
  3604.                       Message(assem_w_comm_not_supported);
  3605.                       while actasmtoken <> AS_SEPARATOR do
  3606.                        Consume(actasmtoken);
  3607.                    end;
  3608.                  end;
  3609.         AS_OPCODE: Begin
  3610.                    instr.init;
  3611.                    BuildOpcode;
  3612.                    instr.numops := operandnum;
  3613.                    if instr.labeled then
  3614.                      ConcatLabeledInstr(instr)
  3615.                    else
  3616.                      ConcatOpCode(instr);
  3617.                   end;
  3618.         AS_SEPARATOR:Begin
  3619.                      Consume(AS_SEPARATOR);
  3620.                      { let us go back to the first operand }
  3621.                      operandnum := 0;
  3622.                     end;
  3623.         AS_END: ; { end assembly block }
  3624.     else
  3625.       Begin
  3626.          Message(assem_e_assemble_node_syntax_error);
  3627.          { error recovery }
  3628.          Consume(actasmtoken);
  3629.       end;
  3630.     end; { end case }
  3631.   end; { end while }
  3632.   { check if there were undefined symbols.   }
  3633.   { if so, then list each of those undefined }
  3634.   { labels.                                  }
  3635.   if assigned(labellist.First) then
  3636.   Begin
  3637.     labelptr := labellist.First;
  3638.     While labelptr <> nil do
  3639.       Begin
  3640.          nextlabel:=labelptr^.next;
  3641.          if not labelptr^.emitted  then
  3642.           Message1(assem_e_local_sym_not_found_in_asm_statement,'.L'+labelptr^.name^);
  3643.          labelptr:=nextlabel;
  3644.       end;
  3645.   end;
  3646.   if p<>store_p then
  3647.     begin
  3648.        Message(assem_e_assembler_code_not_returned_to_text);
  3649.        p:=store_p;
  3650.     end;
  3651.   assemble := genasmnode(p);
  3652.   labellist.done;
  3653.   Message(assem_d_finish_att);
  3654. end;
  3655.  
  3656.  
  3657. var
  3658.  old_exit: pointer;
  3659.  
  3660.     procedure ratti386_exit;{$ifndef FPC}far;{$endif}
  3661.  
  3662.       begin
  3663.          if assigned(iasmops) then
  3664.            dispose(iasmops);
  3665.          exitproc:=old_exit;
  3666.       end;
  3667.  
  3668.  
  3669. Begin
  3670.  line:=''; { Initialization of line variable.
  3671.              No 255 char coonst string in version 0.9.1 MVC}
  3672.  old_exit := exitproc;
  3673.  exitproc := @ratti386_exit;
  3674. end.
  3675.  
  3676. {
  3677.   $Log: ratti386.pas,v $
  3678.   Revision 1.2.2.1  1998/05/25 22:57:32  carl
  3679.     * CALL prblem fixed
  3680.     * one operand opcodes fixed
  3681.  
  3682.   Revision 1.2  1998/03/30 15:53:01  florian
  3683.     * last changes before release:
  3684.        - gdb fixed
  3685.        - ratti386 warning removed (about unset function result)
  3686.  
  3687.   Revision 1.1.1.1  1998/03/25 11:18:15  root
  3688.   * Restored version
  3689.  
  3690.   Revision 1.21  1998/03/10 16:27:44  pierre
  3691.     * better line info in stabs debug
  3692.     * symtabletype and lexlevel separated into two fields of tsymtable
  3693.     + ifdef MAKELIB for direct library output, not complete
  3694.     + ifdef CHAINPROCSYMS for overloaded seach across units, not fully
  3695.       working
  3696.     + ifdef TESTFUNCRET for setting func result in underfunction, not
  3697.       working
  3698.  
  3699.   Revision 1.20  1998/03/10 01:17:27  peter
  3700.     * all files have the same header
  3701.     * messages are fully implemented, EXTDEBUG uses Comment()
  3702.     + AG... files for the Assembler generation
  3703.  
  3704.   Revision 1.19  1998/03/09 12:58:13  peter
  3705.     * FWait warning is only showed for Go32V2 and $E+
  3706.     * opcode tables moved to i386.pas/m68k.pas to reduce circular uses (and
  3707.       for m68k the same tables are removed)
  3708.     + $E for i386
  3709.  
  3710.   Revision 1.18  1998/03/04 17:34:01  michael
  3711.   + Changed ifdef FPK to ifdef FPC
  3712.  
  3713.   Revision 1.17  1998/03/03 22:38:30  peter
  3714.     * the last 3 files
  3715.  
  3716.   Revision 1.16  1998/03/02 01:49:21  peter
  3717.     * renamed target_DOS to target_GO32V1
  3718.     + new verbose system, merged old errors and verbose units into one new
  3719.       verbose.pas, so errors.pas is obsolete
  3720.  
  3721.   Revision 1.15  1998/02/13 10:35:42  daniel
  3722.   * Made Motorola version compilable.
  3723.   * Fixed optimizer
  3724.  
  3725.   Revision 1.14  1998/02/12 11:50:41  daniel
  3726.   Yes! Finally! After three retries, my patch!
  3727.  
  3728.   Changes:
  3729.  
  3730.   Complete rewrite of psub.pas.
  3731.   Added support for DLL's.
  3732.   Compiler requires less memory.
  3733.   Platform units for each platform.
  3734.  
  3735.   Revision 1.13  1998/02/07 18:03:55  carl
  3736.     + fwait warning for emulation
  3737.  
  3738.   Revision 1.12  1998/01/19 03:10:52  carl
  3739.     * bugfix number 78
  3740.  
  3741.   Revision 1.11  1998/01/09 19:24:00  carl
  3742.   + externals are now added if identifier is not found
  3743.  
  3744.   Revision 1.10  1997/12/14 22:43:25  florian
  3745.     + command line switch -Xs for DOS (passes -s to the linker to strip symbols from
  3746.       executable)
  3747.     * some changes of Carl-Eric implemented
  3748.  
  3749.   Revision 1.9  1997/12/09 14:07:14  carl
  3750.   + added better error size checkimg -- otherwise would cause problems
  3751.     with intasmi3
  3752.   * bugfixes as in rai386
  3753.   * BuildRealConstant gave out Overflow errors (hex/bin/octal should be
  3754.     directly decoded into real)
  3755.   * bugfix of MOVSX/MOVZX instruction
  3756.   * ConcatOpCode op_csymbol gave out a Runerrore 216 under each test
  3757.     I performed, or output a nil symbol -- so removed.
  3758.   * All identifiers must be in uppercase!!!
  3759.     (except local labels and directives)
  3760.   + supervisor stuff only possible when compiling the system unit
  3761.  
  3762.   Revision 1.7  1997/12/04 12:21:09  pierre
  3763.     +* MMX instructions added to att output with a warning that
  3764.        GNU as version >= 2.81 is needed
  3765.        bug in reading of reals under att syntax corrected
  3766.  
  3767.   Revision 1.6  1997/12/01 17:42:56  pierre
  3768.      + added some more functionnality to the assembler parser
  3769.  
  3770.   Revision 1.5  1997/11/28 15:43:23  florian
  3771.   Fixed stack ajustment bug, 0.9.8 compiles now 0.9.8 without problems.
  3772.  
  3773.   Revision 1.4  1997/11/28 15:39:46  carl
  3774.   - removed reference to WriteLn and replaced in inasmxxx
  3775.   * uncommented firstop and lastop (otherwise can cause bugs)
  3776.  
  3777.   Revision 1.3  1997/11/28 14:26:24  florian
  3778.   Fixed some bugs
  3779.  
  3780.   Revision 1.2  1997/11/28 12:05:44  michael
  3781.   Changed comment delimiter to braces
  3782.   CHanged use of ord to typecast with longint
  3783.   Changed line constant to variable. Added initialization. v0.9.1 chokes
  3784.   on 255 length constant strings.
  3785.   Boolean expressions are now non-redundant.
  3786.  
  3787.   Revision 1.1.1.1  1997/11/27 08:33:01  michael
  3788.   FPC Compiler CVS start
  3789.  
  3790.  
  3791.   Pre-CVS log:
  3792.  
  3793.  
  3794.   CEC   Carl-Eric Codere
  3795.   FK    Florian Klaempfl
  3796.   PM    Pierre Muller
  3797.   +     feature added
  3798.   -     removed
  3799.   *     bug fixed or changed
  3800.  
  3801.   14th november 1997:
  3802.    * fixed bug regarding ENTER and push imm8 instruction (CEC)
  3803.    + fixed conflicts with fpu instructions. (CEC).
  3804.    + adding real const support. (PM).
  3805.  
  3806. }
  3807.  
  3808.